首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

通过实例分析让您彻底理解NFS协议

NFS协议最为权威的参考文档自然是RFC文档了。以NFSv3为例,对应的RFC文档是RFC1813。但是当我们初次接触该文档的时候有种找不到北的感觉。以NFSv3的WRITE例程为例,在文档中的说明如下图所示,从该图中似乎看不太明白协议的具体定义。

图1 NFS 写协议描述

其实要理解上述内容并不困难,首先是要结合前面文章介绍的RPC的内容来理解,这样再理解NFS协议的内容就不会太难了。

在RPC协议中我们了解到,RPC实现了一种远程函数调用的机制。也就是客户端在调用基于RPC的函数(存根)时,该函数会被封装成网络消息发送到服务端,并且激活一个服务端的函数(存根)。并且,通常客户端的存根与服务端的存根是一一对应的。

图2 存根函数

RPC实现了函数的远程调用,但是并没有定义函数的参数。而函数的参数则是在NFS中定义的(其实函数ID也是在NFS定义的)。对于图1中的描述,WRITE3args就是写操作的参数,WRITE3resok就是返回值。而NFSPROC2_WRITE=7则是写操作的ID,也就是存根ID。

其实通过NFS协议中的定义也可以看出端倪,如果我们简化一下,其实就是一个函数原型。

WRITE3res= NFSPROC2_WRITE(WRITE3args)

在NFS协议中定义了一组操作,这些操作与文件系统的操作基本上一一对应。比如读数据,写数据,创建文件,查找文件和删除文件等。这样,用户的一个文件操作,基本上就可以从主机端传到存储端来处理。如下图是NFSv3协议的一个子集。

图3 NFS协议子集

针对NFSv3定义的函数集,在内核NFS文件系统中都有对应的实现,如下代码是Linux内核NFS的代码。通过实现代码可以看到内核对NFS协议的实现。

图4 NFS在内核中的实现

介绍到这里,大家应该对NFS协议有了一个感性的认识了。为了让大家更加深切的理解NFS协议以及与RPC协议之间的关系。我们可以通过WireShark抓一下NFS的数据包。以写数据为例,抓获的数据包如下所示。

WireShark是可以识别RPC和NFS协议的。如图所示,我们展开NFS协议的内容,如红色方框和绿色方块所示。其中红色方框中的内容在RPC协议中编码,而绿色方框的内容则在RPC外编码,这些内容其实就是函数的参数,如文件句柄,请求偏移,长度和模式等等,以及要写入的数据。

内核中NFS写数据的流程稍微有点复杂,我们后面会专门介绍。本文我们挑选一个比较简单的函数来介绍,比如创建文件。创建文件的NFS定义如下所示。

我们可以通过WireShark捕获创建文件过程的数据包,从结果可以看到,创建文件包括where(父目录和新文件名),模式和认证信息。这个与协议的定义是完全一致的。

然后我们再结合看一下主机端的代码实现。对于创建文件,其代码实现为nfs3_proc_create。我们看一下该函数对参数的初始化部分。可以看出,这里主要初始化RPC需要的参数,而且参数内容与协议一致(这句话其实是废话)。

最后,该函数会调用nfs3_do_create->rpc_call_sync,rpc_call_sync是RPC的API,前面初始化的参数数据会传给该API,然后RPC会封装为数据包(我们在WireShark抓获的样子),然后发送到服务端。

本文从整体上介绍了一下NFS协议,以及NFS与RPC协议的关系。后面我们将结合更多的实例来介绍NFS协议与代码实现。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OQIOTj3yStuufZaaj2_IeTGg0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券