Glusterfs之nfs模块源码分析
一、网络文件系统概述
Sun Microsystems公司于1984年推出了一个在整个计算机工业中被广泛接受的远程文件存取机制,它被称为Sun的网络文件系统(Network File System),或者简称为NFS。该机制允许在一台计算机上运行一个服务器,使对其上的某些或所有文件都可以进行远程存取,还允许其他计算机上的应用程序对这些文件进行存取。
它使我们能够达到文件的共享。当使用者想用远端档案时只要用"mount"就可把remote档案系统挂接在自己的档案系统之下,使得远端的文件操作上和本地机器的文件没两样。一个应用程序可以打开(Open)一个远程文件以进行存取,可以从这个文件中读取(Read)数据,向该文件中写入(Write)数据,定位(Seek)到文件中的某个指定位置(开始、结尾或者其他地方),最后当使用完毕后关闭(Close)该文件。并且这些操作都是对编程者透明的,操作方法和对本地文件的操作方法完全一样。
二、 NFS 协议
NFS协议使用NFS,客户端可以透明地访问服务器中的文件系统,这不同于提供文件传输的FTP协议。FTP会产生文件一个完整的副本;NFS只访问一个进程引用文件部分,并且一个目的就是使得这种访问透明。这就意味着任何能够访问一个本地文件的客户端程序不需要做任何修改,就应该能够访问一个NFS文件。NFS是一个使用SunRPC构造的客户端/服务器应用程序,其客户端通过向一台NFS服务器发送RPC请求来访问其中的文件。尽管这一工作可以使用一般的用户进程来实现,即NFS客户端可以是一个用户进程,对服务器进行显式调用,而服务器也可以是一个用户进程。因为两个理由,NFS一般不这样实现。首先访问一个NFS文件必须对客户端透明,因此NFS的客户端调用是由客户端操作系统代表用户进程来完成的;其次,出于效率的考虑,NFS服务器在服务器操作系统中实现。如果NFS服务器是一个用户进程,每个客户端请求和服务器应答(包括读和写的数据)将不得不在内核和用户进程之间进行切换,这个代价太大。第3版的NFS协议在1993年发布,下图所示为一个NFS客户端和一台NFS服务器的典型结构。
图1 NFS 客户端和 NFS 服务器的典型结构
(1)访问一个本地文件还是一个NFS文件对于客户端来说是透明的,当文件被打开时,由内核决定这一点。文件被打开之后,内核将本地文件的所有引用传递给名为“本地文件访问”的框中,而将一个NFS文件的所有引用传递给名为“NFS客户端”的框中。
(2)NFS客户端通过其TCP/IP模块向NFS服务器发送RPC请求,NFS主要使用UDP,最新的实现也可以使用TCP。
(3)NFS服务器在端口2049接收作为UDP数据包的客户端请求,尽管NFS可以被实现为使用端口映射器,允许服务器使用一个临时端口,但是大多数实现都是直接指定UDP端口2049。
(4)当NFS服务器收到一个客户端请求时,它将这个请求传递给本地文件访问例程,然后访问服务器主机上的一个本地的磁盘文件。
(5)NFS服务器需要花一定的时间来处理一个客户端的请求,访问本地文件系统一般也需要一部分时间。在这段时间间隔内,服务器不应该阻止其他客户端请求。为了实现这一功能,大多数的NFS服务器都是多线程的——服务器的内核中实际上有多个NFS服务器在NFS本身的加锁管理程序中运行,具体实现依赖于不同的操作系统。既然大多数UNIX内核不是多线程的,一个共同的技术就是启动一个用户进程(常被称为“nfsd”)的多个实例。这个实例执行一个系统调用,使其作为一个内核进程保留在操作系统的内核中。
( 6 ) 在客户端主机上, NFS 客户端需要花一定的时间来处理一个用户进程的请求。 NFS 客户端向服务器主机发出一个 RPC 调用,然后等待服务器的应答。为了给使用 NFS 的客户端主机上的用户进程提供更多的并发性,在 客户端内核中一般运行着多个NFS客户端,同样具体实现也依赖于操作系统。
三、NFS 的工作原理和服务进程的作用
在 Linux 中, NFS 和服务进程是两个不同的概念,但它们确实紧密联系在一起。首先,先介绍 NFS 的工作原理。
第一节、NFS 的工作原理启动 NFS 文件服务器时, /etc/rc.local 会自动启动 exportfs 程序,指定可以导出的文件或目录,而所能挂载的也只能是其所指定的目录。
NFS 是基于 XDR/RPC 协议的。 XDR ( eXternal Data Representation ,即外部数据表示法)提供一种方法,把数据从一种格式转换成另一种标准数据格式表示法,确保在不同的计算机、操作系统及程序语言中,所有数据代表的意义都是相同的。
RPC ( Remote Procedure Call ,远程程序调用)请求远程计算机给予服务。客户机通过网络传送 RPC 到远程计算机,请求服务。
NFS 运用 RPC 传送数据的方法有以下几步:
( 1 )客户送出信息,请求服务。
( 2 )客户占位程序把客户送出的参数转换成 XDR 标准格式,并用系统调用把信息送到网络上。
( 3 )信息经过网络送达远程主机系统。
( 4 )远程主机将接受到的信息传给服务器占位程序。
( 5 )把 XDR 形式的数据,转换成符合主机端的格式,取出客户发出的服务请求参数,送给服务器。
( 6 )服务器给客户发送服务的逆向传送过程。
服务进程是系统在启动计算机后自动运行的程序,包括对网络的连接、网络协议的加载、图形桌面的显示、文件系统的加载等, Linux 系统中常见的进程包括以下几种。
(1 ) nfsd
根据客户端对文件系统的需求,启动文件系统请求服务进程,响应客户的请求,而一般文件系统请求服务进程的数目是 8 ,这也是在 rc.local 中写 nfsd 8 & 的原因。
(2 ) biod
此进程是在 NFS 客户端上用的,用来启动异步块 I/O 服务进程来建立 Buffer Cache ,处理在客户机上的读写。 (3 ) mountd
这是个 RPC 服务器。启动 rpc.mountd 服务进程后, mountd 会读取 /etc/xtab 查看哪一台客户机正在挂载哪一个文件系统,并回应客户机所要挂载的路径。
(4 ) inetd Internet services 服务进程
当系统启动时, rc.local 会启动 inetd 读取 inetd.conf 配置文件,读取网络上所有服务器的地址,链接启动 inetd.conf 中所有的服务器。当客户机请求服务时, inetd 就会启动相关的服务进程,如 user 使用 telnet 时, inetd 启动 telnetd 配合 user telnet 的需求,其余像 ftp 、 finger 、 rlogin 等应用程序, inetd 也都会启动相对应的服务程序 ftpd 、 fingerd 、 rloingd 等。
(5 ) portmap 服务程序
主要功能是将 TCP/IP 通信协议的端口数字转换成 RPC 程序数字,因为这样客户端才能进行 RPC 调用。一般 RPC 服务器是被 inet 启动的,所以 portmap 必须在 inetd 之前启动,否则无法进行 RPC 调用。
四、 NFS 服务器之 RPC
因为 NFS 支持的功能相当多,而不同的功能都会使用不同的程序来启动。每启动一个功能就会启用一些端口来传输数据,因此 NFS 的功能所对应的端口才没有固定,而是采用随机取用一些未被使用的小于 724 的端口来作为传输之用。但如此一来又造成客户端要连接服务器时的困扰,因为客户端要知道服务器端的相关端口才能够联机,此时我们需要远程过程调用( RPC )的服务。 RPC 最主要的功能就是指定每个 NFS 功能所对应的端口号,并且回报给客户端,让客户端可以连接到正确的端口上。当服务器在启动 NFS 时会随机选用数个端口,并主动地向 RPC 注册。因此 RPC 可以知道每个端口对应的 NFS 功能。然后 RPC 固定使用端口 111 来监听客户端的请求并回报客户端正确的端口,所以可以让 NFS 的启动更为容易。注意,启动 NFS 之前,要先启动 RPC ;否则 NFS 会无法向 RPC 注册。另外,重新启动 RPC 时原本注册的数据会不见,因此 RPC 重新启动后它管理的所有程序都需要重新启动以重新向 RPC 注册。
当客户端有 NFS 文件要存取请求时,它如何向服务器端要求数据?
( 1 )客户端会向服务器端的 RPC ( port 111 )发出 NFS 文件存取功能的询问请求。
( 2 )服务器端找到对应的已注册的 NFS daemon 端口后会回报给客户端。
( 3 )客户端了解正确的端口后,就可以直接与 NFS 守护进程来联机。
由于 NFS 的各项功能都必须要向 RPC 注册,因此 RPC 才能了解 NFS 服务的各项功能的 port number 、 PID 和 NFS 在主机所监听的 IP 等,而客户端才能够通过 RPC 的询问找到正确对应的端口。即 NFS 必须要有 RPC 存在时才能成功地提供服务,因此我们称 NFS 为 RPC Server 的一种。事实上,有很多这样的服务器都向 RPC 注册。例如, NIS ( Network Information Service )也是 RPC Server 的一种。所以如下图所示,不论是客户端还是服务器端,要使用 NFS 都需要启动 RPC 。
图 2 NFS 与 RPC 服务及操作系统的相关性
NFS 协议从诞生到现在为止,已经有多个版本,如 NFS V2 ( rfc794 )及 NFS V3 ( rfc1813 )(最新的版本是 V4 ( rfc307 ))。最早, SUN 公司曾将 NFS V2 设计为只使用 UDP ,主要原因是当时机器的内存、网络速度和 CPU 的影响,不得不选择对机器负担较轻的方式。而到了 NFS V3 , SUN 公司选择了 TCP 作为默认的传输方式。 V3 相对 V2 的主要区别如下:
( 1 )文件尺寸: V2 最大只支持 32 位的文件大小( 4 GB ),而 V3 新增加了支持 64 位文件大小的技术
( 2 )文件传输尺寸: V3 没有限定传输尺寸, V2 最多只能设定为 8 KB ,可以使用 -rsize and -wsize 来设定
( 3 )返回完整的信息: V3 增加和完善了返回错误和成功信息,对于服务器的设置和管理能带来很大好处
( 4 )增加了对 TCP 传输协议的支持: V2 只提供了对 UDP 的支持,在一些高要求的网络环境中有很大限制; V3 增加了对 TCP 的支持。 UDP 有着传输速度快且非连接传输的便捷特性,但是在传输上没有 TCP 稳定。当网络不稳定或者黑客入侵时很容易使 NFS 的性能大幅度降低,甚至使网络瘫痪。所以对于不同情况,网络要有针对性地选择传输协议。 NFS 的默认传输协议是 UDP ,然而 RHEL 4.0 内核提供了对通过 TCP 的 NFS 的支持。要通过 TCP 来使用 NFS ,在客户端系统上挂载 NFS 导出的文件系统时包括一个“ -o tcp ”选项。使用 TCP 的优点和缺点如下:
1 )被提高了的连接持久性,因此获得的 NFS stale file handles 消息就会较少。
2 )载量较大的网络的性能会有所提高,因为 TCP 确认每个分组,而 UDP 只在完成时才确认。
3 ) TCP 具有拥塞控制技术( UDP 根本没有),在一个拥塞情况严重的网络上, UDP 分组是被首先撤销的类型。使用 UDP 意味着,如果 NFS 正在写入数据(单元为 8 KB 的块),所有这 8 KB 数据都需要被重新传输。由于 TCP 的可靠性, 8 KB 数据中只有一部分需要重新传输。
4 )错误检测。当 TCP 连接中断(由于服务器停止),客户端就会停止发送数据而开始重新连接。 UDP 是无连接的,使用它的客户端就会继续给网络发送数据直到服务器重新上线为止。
5 ) TCP 的费用在性能方面的提高并不显著。
( 5 )异步写入特性。
( 6 )改进了服务器的 mount 性能。
( 7 )有更好的 I/O 写性能。
( 8 )更强的网络运行效能,使得网络运行更为有效。
( 9 )更强的灾难恢复功能。
在 Linux 上, UDP 是默认使用的协议。作为服务器别无选择。但作为客户端,可以使用 TCP 和其他使用 TCP 的 UNIX NFS 服务器互联。在局域网中使用 UDP 较好,因为局域网有比较稳定的网络保证。使用 UDP 可以带来更好的性能, Linux 默认使用 V2 ,但是也可以通过 mount option 的 nfsvers=n 选择。 NFS 使用 TCP/IP 提供的协议和服务运行于 OSI 层次模型的应用层,如表 1 所示。
表 1 OSI 层次模型上的 NFS
层 数
名 称
功 能
应用层
NFS
表示层
XDR
会话层
RPC
传输层
UDP , TCP
网络层
IP
数据链路层
物理层
Ethernet
分类: glusterfs , 分布式开源软件研究
标签: glusterfs , nfs
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于Glusterfs之nfs模块源码分析的详细内容...