NFS配置.docx
《NFS配置.docx》由会员分享,可在线阅读,更多相关《NFS配置.docx(73页珍藏版)》请在冰豆网上搜索。
![NFS配置.docx](https://file1.bdocx.com/fileroot1/2022-12/31/d06a1cdc-4e8d-4128-9489-b6b0fa3c8247/d06a1cdc-4e8d-4128-9489-b6b0fa3c82471.gif)
NFS配置
Linux网络文件系统
(NFS)分析
浙江大学计算机系98硕
宋鹏王靖滨余可曼
1.网络文件系统概述4
1.1远程文件存取4
1.2网络文件系统概述4
1.3网络文件系统上层实现5
1.3.1Mount安装协议和NFS远程过程5
1.3.2访问文件的具体流程5
1.4网络文件系统下层实现——远程过程调用(RPC)6
1.4.1RPC的概念模型7
1.4.2SUNRPC的定义7
1.4.3SUNRPC的传输层实现机制8
1.4.3.1通信语义8
1.4.3.2动态端口映射9
1.4.4一次RPC远程调用的具体流程9
2.Linux的NFS系统框架11
2.1源码分析环境11
2.2Linux下NFS的体系结构12
2.3NFS的Client端12
2.3.1Client端的VFS层13
2.3.2Client端的RPC层20
2.3.3Client端的NFS层27
2.3.3.1NFS过程层27
2.4NFS的Server端33
2.4.1Server端的RPC层33
2.4.2Server端的NFS层37
2.4.3NFSServer端启动39
2.4.4nfsservctl系统调用实现40
2.4.5RPC鉴别机制46
3Mount安装协议的具体实现48
3.1NFSClient端Mount协议数据结构48
3.2NFSClient端Mount协议实现50
3.2.1 Linux根文件系统的NFSMount协议安装51
3.2.1.1nfs_root_setup函数的实现52
3.2.1.2nfs_root_mount函数的功能54
3.2.2 命令行下的动态NFSMount协议安装60
3.2.2.1nfs_read_super函数的实现60
4 NFS文件操作具体流程64
4.1NFS文件协议的数据结构64
4.2打开一个NFS文件的具体流程65
4.2.1VFS层操作分析65
4.2.2NFS层操作分析67
4.2.3RPC层操作分析69
4.2.4Server端操作分析69
4.3读写一个NFS文件的具体流程70
4.3.1sys_read函数71
4.3.2 nfs_file_read函数72
4.3.3 nfs_readpagenfs_readpage_sync函数72
5NFS文件系统FAQ76
参考文献:
79
1.
网络文件系统概述
1.1远程文件存取
许多早期的网络系统提供了文件传输(Filetransfer)服务,它允许用户把某文件的一个副本从一台机器移到另一台机器上。
而更多近期的网络则提供了文件存取(Fileaccess)服务,即允许某个应用程序从一台远程机器上对某个文件进行存取。
使用远程文件机制对文件进行存取的应用程序,可以同它所要存取的文件驻留在同一台机器上,也可以运行在某台远程机器上。
当一个应用程序要存取一个驻留在某台远程机器上的文件时,该程序的操作系统将调用客户机软件,这个客户机软件与远程机器中的服务器联系,执行对该文件执行所请求的操作。
与文件传输服务不同,该服务的系统并不立即对整个文件进行传输和存储,而是每次要求传送一小块数据。
为了提供对驻留在某台计算机上的某些或所有文件的远程存取能力,系统管理员必须让该计算机运行一个可以对存取请求进行响应的服务器。
这个服务器对每个请求进行检查,以验证该客户是否具有对指定文件进行存取的权利,然后执行所指明的操作,最后向客户机返回一个结果。
1.2网络文件系统概述
SunMicrosystems公司于1984年推出了一个在整个计算机工业中被广泛接受的远程文件存取机制,它被称为Sun的网络文件系统(NetworkFileSystem),或者简称为NFS。
该机制允许在一台计算机上运行一个服务器,使对其上的某些或所有文件都可以进行远程存取,还允许其他计算机上的应用程序对这些文件进行存取。
它使我们能够达到文件的共享。
当使用者想用远端档案时只要用"mount"就可把remote档案系统挂接在自己的档案系统之下,使得远端的文件操作上和本地机器的文件没两样。
一个应用程序可以打开(Open)一个远程文件以进行存取,可以从这个文件中读取(Read)数据,向该文件中写入(Write)数据,定位(Seek)到文件中的某个指定位置(开始、结尾或者其他地方),最后当使用完毕后关闭(Close)该文件。
并且这些操作都是对编程者透明的,操作方法和对本地文件的操作方法完全一样。
下面的两节我们将继续介绍Sun的网络文件系统的具体实现,这对于了解下一章Linux中NFS的实现提供了很好的理论背景。
1.3网络文件系统上层实现
1.3.1Mount安装协议和NFS远程过程
NFS的实现被分离成两个独立的程序来实现,分别是Mount安装协议和NFS远程过程调用。
Mount安装协议是实现文件访问的开端。
它的主要功能是获取远程机器上的不同文件系统结构并返回所要访问的文件系统根句柄,作为以后对该文件系统进行操作的根本。
在下一节中我们将介绍PRC(远程过程调用)的基础知识,而关于PRC如何实现NFS的上述两部分功能,我们将在下一章中,结合具体的Linux函数进行分析。
相信这样,更能加深这部分知识的理解。
1.3.2访问文件的具体流程
上面我们看到了NFS文件系统的主要数据结构,以及实现文件系统的两部分重要构成。
下面总结一下NFS中怎样实现对一个目标文件的访问。
在NFS中,每次对远程文件系统上的通过一个称之为”文件句柄”(file-handle)的数据结构来实现对远程机器上目标文件的操纵。
首先对文件名在本地进行解析。
这一过程与传统UNIX中的文件名解析过程类似。
即一次解析一个全路径名的一部分。
它从分层结构的根及路径的开始出发,重复地从路径中取出下一部分,并找出一个具有该名字的文件或子目录。
在NFS系统中,得到一个目的文件句柄不是一步完成的,而是分多个步骤实现的。
首先是由Mount安装协议取得该NFS服务器上的分层文件结构信息,并取得相应文件系统的根句柄。
在得到一个远程文件系统的根句柄后,结合本地对文件名字解析的结果,可以调用NFS的远程过程,在当前远程文件系统根句柄下取出各个子目录的文件句柄返回,检查返回的文件句柄,得到最后的所要访问的文件句柄。
得到文件句柄的流程图如下所示,它展示了当客户机要在服务器的分层结构中查找一个路径为/a/b/c的文件时,客户机和服务器之间所进行的信息交换。
句柄Hr
在Hb中查找c
句柄Hc
句柄Hb
句柄Ha
在Ha中查找b
在Hr中查找a
请求根句柄
发送的报文
服务器端
客户机端
以后对该文件的各种操作,就通过该文件句柄来实现了。
各种操作可以参见前一小节上面所列出的NFS远程过程。
1.4网络文件系统下层实现——远程过程调用(RPC)
由于NFS的底层实现是采用远程过程调用(RPC)来实现的。
因此在这里,我们将先概述一下RPC的基本模型、机制以及SUNRPC的定义。
在下一章中,我们将详细介绍NFS的Mount协议以及对文件操作的远程过程是如何用RPC来具体实现的。
1.4.1RPC的概念模型
远程过程调用模型主要来自于传统编程语言中的过程调用机制。
过程调用提供了一个强有力的抽象,它允许程序员将一个程序划分为一些小的、可管理的、易于理解的片段。
它可以给出程序执行的概念性模型的简单明了的实现。
图一远程过程调用模型
计算机二
计算机一
Proc7
Proc4
Proc6
Proc5
Proc3
Proc2
Proc1
main
RPC使用了和传统程序一样的过程抽象,只是它允许一个过程的边界跨越两台计算机。
图一展示了远程过程调用模型如何将一个程序划分为两片,每片在一个单独的计算机上执行。
根据过程执行模型,单个控制线索流经所有过程。
计算机从一个主程序开始执行,它将一直继续下去,直到遇到一个过程调用。
这个调用使执行转入到某个指定的过程代码并继续执行,直到遇到一个return语句。
因此在RPC中,一个远程过程调用把控制权传递给被调用的过程,把调用过程的执行挂起。
而远程的服务器则实现这个过程,当执行完毕,它给客户机一个响应,这对应于过程模型的return。
使控制权返回给调用者,被调用过程停止执行。
这个过程是可嵌套的。
1.4.2SUNRPC的定义
SunMicrosystems公司定义了一个特定形式的远程过程调用。
它称为SunRPC。
它定义了调用者(客户机)发出的调用服务器中的某个远程过程的报文的格式、参数的格式,以及被调用过程返回给调用者的结果的格式。
SunRPC通过定义一个远程执行环境而扩展了远程过程调用模型。
它定义了一个远程程序,把它作为在远程机器上执行的软件的基本单元。
每个远程程序对应于我们所设想的一个服务器,它包括一组远程过程以及全局数据。
在一个远程程序中的所有过程都能共享它的全局数据。
SUNMicrosystems公司设计了一种外部数据表示,它规定了在网络传输数据时如何表示成公共形式的数据。
Sun的外部数据表示XDR已成为大多数客户机-服务器应用的一个事实上的标准。
RPC远程过程调用的数据传输的数据必须遵循XDR标准。
SunRPC标准说明,在某个计算机上执行的每个远程程序都必须分配一个唯一的32比特整数,调用者使用该整数来标识这个程序。
并且,针对每个远程程序的整数型还有一个版本号,使程序可以不必获得一个新的程序号就能改变某个远程过程的细节。
此外,SUNRPC为每一个给定的远程程序中的远程过程分配了一个整数标识符。
因此,每个RPC报文通过一个三元组来标识某台给定计算机上的所期望的接受者,这个三元组是:
(prog,vers,proc)
在此,prog标识远程程序,vers表示抱文所要发往的程序的版本号,proc表示该远程程序中的某一个远程过程。
1.4.3SUNRPC的传输层实现机制
1.4.3.1通信语义
为保证RPC语义的实现,我们必须在良种可能中进行选择。
一方面,为尽量使远程过程调用的行为像一个本地过程调用,RPC应该使用一种像TCP这样可靠的运输,而且应该对程序员保证可靠性。
另一方面,为允许程序员使用高效率的、无连接的运输协议,远程过程调用机制应当支持用UDP这样的数据报协议进行通信。
因为UDP传输的不可靠性,在传输过程中可能因为报文的丢失,使得调用者无法做出应答,而导致远程过程被多次调用。
因此,选择UDP作为PRC应用传输协议的程序员,他们所构建的程序必须要能容忍零或多次执行语义。
在我们下一章的Linux源代码分析中,我们将看到,Linux对于RPC远程过程调用的实现是采用UDP作为它的传输层应用协议来进行的。
目前的Linux系统中,并没有采用TCP协议来实现网络文件系统的传输层应用。
Linux设计者在这方面的考虑应该是基于实现NFS系统传输的高效性,对于TCP协议的支持相信Linux将会在以后实现。
1.4.3.2动态端口映射
在使用TCP或UDP协议进行远程数据传输的时候,需要指定一个服务器的通信端口号。
但是,SUNRPC引出了一个有趣的问题:
因为它使用32位比特数来标识远程程序,而UDP和TCP运输协议使用16比特数的协议端口号来标识通讯端点,这就有可能超出协议端口的范围。
因此,不可能将RPC程序号直接映射到协议端口号,因此RPC不能象其他通讯协议一样使用分配知名端口的协议。
但是尽管RPC程序的潜在数量超过了分配知名端口的能力,但RPC和其他服务没有什么不同。
在任意给定时间内,单个计算机仅仅执行少量的远程程序。
因此,只要端口分配是临时的,每个RPC程序可以获得一个协议端口号,并且使用这个端口号进行通信。
PRC对于协议端口的获得是通过一个称之为端口映射器的机制来实现的。
因为服务器端口映射是临时的,每个RPC程序在数据传输前可以获得一个协议端口号,并且使用这个传输端口进行通信。
然而,作为发起远程过程调用的客户机程序,除了知道它所希望与之联系的机器地址以及RPC程序号以外,它还必须在开始执行之后获得一个协议端口,否则不能直接联系远程程序。
这种端口映射必须是动态的,因为如果机器重启动或者RPC程序再次开始执行,端口可能会改变。
ONCRPC机制包含了一个动态映射服务。
提供RPC程序的每台机器维护着一个端口映射数据库,而且提供了一种允许调用者将RPC端口号映射为协议端口的机制。
它在每台机器中用一个服务器维护这一个小数据库,这个服务器被称为RPC端口映射器。
一个RPC程序一旦注册了自己,其他机器上的调用者就可以通过向端口映射器发送一个请求来找到它的协议端口。
1.4.4一次RPC远程调用的具体流程
通过以上两小节的讨论,我们对RPC体系的实现从上到下有了一个概念上的认识。
这一小节中,将具体说明一次远程过程调用的具体实现,从而加深对这部分实现机制的认识。
一个RPC远程过程调用的流程如下:
1.需要运行一个远程程序时,本地机器向端口映射器发出注册请求,将一个三元组加到数据库:
(RPC程序号,协议端口号,版本号)并分配给该远程程序一个通信协议端口。
2.调用方发送RPC查找请求,调用TCP或UDP协议,将请求报文发送到服务器端口映射器的知名端口,在给定一RPC程序号和版本号时查找其协议端口。
3.端口映射器返回这个指定程序当前正在使用的协议端口号。
4.调用者在得到了该目标程序正在使用的端口号后,可以直接联系远程程序了。
此后,调用方将调用的远程过程的名称、类型、版本号、一些传输的XDR数据结构,进行参数的序列化,构成RPC报文。
在调用方和服务器之间实现通信传输。
2.
Linux的NFS系统框架
NFS是由客户和服务器共同合作实现的:
在客户一边,通过一些核心函数调用来使用远程文件系统;在服务器一边,由NFS服务器监听进程来提供文件数据。
主要有两个监听进程moutd和nfsd,其中moutd用来监听客户的安装请求,并发送相应的应答信息,如客户端地址和服务器地址等;而nfsd进程用来监听客户端的读写文件请求并返回相应的文件数据。
文件的访问对客户来说是完全透明的,并且NFS可以跨越各种服务器和主机平台进行。
同其他文件系统在底层是通过访问磁盘不同,NFS在底层是通过RPC(远程过程调用)协议来实现文件访问的。
NFS的主要优点是可以将占用大量磁盘空间的或用户共享的数据只保存在一个NFS服务器上,其它主机要访问这些数据,只需通过NFS将其安装到本地目录进行透明的访问。
所谓透明的访问,是指访问这些文件与访问本地的一般文件的用户界面是一致的,并不需要额外的命令。
如下图:
(NFS服务器)
2.1源码分析环境
我们分析的Linux内核代码版本为2.2.5(套装系统为RedHat6.0)。
Linux从2.2.X版本开始,对内核中NFS部分的内容有了重大的改进。
增加了很多内容,重写了很多函数,功能有了很大的改进。
其中比2.0.34版本的内核的主要改进有:
在内核中增加了NFS的Server端内容。
而在2.0.34版本中Server端并不在内核中支持,需要外部Server程序。
将NFS与RPC的实现分开,使RPC可以不仅为NFS提供服务,还可以为其他网络协议提供服务。
显著增强了RPC的功能,增加了如RPC调用的调度、权限验证、端口映射器以及支持同步和异步调用两种方式等功能。
在这一章中,我们将主要介绍Linux下网络文件系统所用到的主要数据结构及他们之间的关系。
在下一章开始,我们将详细阐述系统运作的流程。
2.2Linux下NFS的体系结构
Linux下网络文件系统主要分为两个部分:
NFSClient端、NFSServer端,即采用Client-Server体系结构。
其中Client方面主要负责处理用户对远程文件的操作请求,并把请求的内容按一定的包格式从网络发给文件所在的Server方面。
而Server方面则接受Client方面的请求,调用本机的VFS的函数进行文件的实际操作,并把结果按一定格式返回给Client方面。
而Client方面得到Server的返回结果,把它返回给用户。
这是Linux下网络文件系统的基本体系结构:
NFS体系结构
服务器端
客户端
VFS
Socket
XDR
RPC
NFS
安装协议
Socket
XDR
RPC
NFS
安装协议
VFS
2.3NFS的Client端
由上图所示,Client端从高层到底层由四部分组成:
VFS、NFS、RPC、Socket。
下面将介绍各个部分的实现以及他们之间的接口。
2.3.1Client端的VFS层
Linux最大的特点之一是它支持多种文件系统,如:
EXT、EXT2、XIA、MINIX、UMSDOS、MSDOS、VFAT、PROC、SMB、NCP、ISO9660、SYSV、HPFS、SFFS和UFS等等,甚至还支持NFS。
它之所以能支持这么多的文件系统,是由于它在具体的文件系统上增加了一层抽象层:
VFS文件系统。
VFS文件系统将独立于具体文件系统的数据和操作集中在自身之中,并通过数据结构中的UNION类型和函数指针将具体的文件系统包容进来。
这种分层的概念,使得Linux不仅可以有良好的兼容性,而且也使它有较大的可扩充性。
VFS文件系统是建立在具体文件系统上的一个抽象层次。
它必须管理在Linux系统中的每一个具体的文件系统。
为此,它维护着众多的数据结构,这些数据结构描述了整个文件系统和实际的安装上的文件系统。
其中最主要的数据结构有super_block、inode、file、file_system_type、dentry等。
在这些数据结构中,包含了一些与具体文件系统的接口,下面将结合NFS层逐个进行介绍这些数据结构及其和NFS的接口。
NFS的常数和文件模式
定义了六种基本常数来指明协议所用数组的大小。
另外,象UNIX一样,NFS假定每个文件或目录一个指明其类型和存取保护的模式(mode)。
图23.7列出了NFS模式整数的单个比特及其含义。
定义直接对应于UNIX的stat函数的返回值。
#defineNFS_PORT2049
#defineNFS_MAXDATA8192
#defineNFS_MAXPATHLEN1024
#defineNFS_MAXNAMLEN255
#defineNFS_MAXGROUPS16
#defineNFS_FHSIZE32
#defineNFS_COOKIESIZE4
#defineNFS_FIFO_DEV(-1)
#defineNFSMODE_FMT0170000
#defineNFSMODE_DIR0040000//这是个目录;类型是NFDIR
#defineNFSMODE_CHR0020000//这是个字符专有文件;类型应该是NFCHR
#defineNFSMODE_BLK0060000//这是个块专有文件:
类型应该是NFBLK
#defineNFSMODE_REG0100000//这是个普通文件;类型应该是NFREG
#defineNFSMODE_LNK0120000//这是个符号连接,类型应该是NFLNK
#defineNFSMODE_SOCK0140000//这是个有名的插口,类型应该是NFSOCK
#defineNFSMODE_FIFO0010000
NFS的调用返回值
协议定义一个常量枚举类型,被用于报告差错状态。
每个远程调用都返回其中的一个值。
该协议的集合命名为stat,如下:
enumnfs_stat{
NFS_OK=0,
NFSERR_PERM=1,
NFSERR_NOENT=2,
NFSERR_IO=5,
NFSERR_NXIO=6,
NFSERR_EAGAIN=11,
NFSERR_ACCES=13,
NFSERR_EXIST=17,
NFSERR_XDEV=18,
NFSERR_NODEV=19,
NFSERR_NOTDIR=20,
NFSERR_ISDIR=21,
NFSERR_INVAL=22,/*thatSunforgot*/
NFSERR_FBIG=27,
NFSERR_NOSPC=28,
NFSERR_ROFS=30,
NFSERR_OPNOTSUPP=45,
NFSERR_NAMETOOLONG=63,
NFSERR_NOTEMPTY=66,
NFSERR_DQUOT=69,
NFSERR_STALE=70,
NFSERR_WFLUSH=99
};
NFS的文件类型:
NFS使用和UNIX相同的基本文件类型。
它定义了服务器在指定文件类型时可使用的枚举值。
enumnfs_ftype{
NFNON=0,//说明不是一个文件
NFREG=1,//一般的数据文件
NFDIR=2,//是一个目录文件
NFBLK=3,//是一个块设备文件
NFCHR=4,//是一个字符设备文件
NFLNK=5,//是一个符号链接
NFSOCK=6,
NFBAD=7,
NFFIFO=8
};
NFS的文件句柄:
在目前的linux版本中,文件句柄定义为一个32字节长度的数组。
在SunMicroSystem的NFS标准中,文件句柄分为许多个字段,其中有必要提及的是其中的随机生成的一个文件索引结点号。
文件生成号的使用主要出于对网络文件访问安全性的考虑出发。
因为一旦客户机知道了远程文件系统服务主机的文件目录结构,以及产生文件句柄的方式,可以很容易地构造出某个指定路径上的文件句柄,并通过该句柄对远程文件系统进行访问。
这样,就违背了网络访问的安全性原则,因此在标准的NFS文件系统中,当文件系统服务器收到客户机的访问请求时,除了返回相应文件的文件句柄以外,还动态地随机生成此文件对应的文件生成号,一般是一个32字节的字符串,提供给客户机。
这样,以后客户机在访问服务器的文件系统时,通过检查文件句柄结构中所带的文件生成号是否匹配,就可以决定是否是一次合法的访问。
这种机制保证了NFS文件系统远程访问的安全性。
structnfs_fh{
chardata[NFS_FHSIZE];
};
NFS的远程过程定义:
这里只定义了各个远程过程的程序号,具体每个过程的功能将在后面介绍。
#defineNFS_PROGRAM100003
#defineNFS_VERSION2
#defineNFSPROC_NULL0
#defineNFSPROC_GETATTR1
#defineNFSPROC_SETATTR2
#defineNFSPROC_ROOT3
#defineNFSPROC_LOOKUP4
#defineNFSPROC_READLINK5
#defineNFSPROC_READ6
#defineNFSPROC_WRITECACHE7
#defineNFSPROC_WRITE8
#defineNFSPROC_CREA