📄 rfc1094.txt
字号:
组织:中国互动出版网(http://www.china-pub.com/)
RFC文档中文翻译计划(http://www.china-pub.com/compters/emook/aboutemook.htm)
E-mail:ouyang@china-pub.com
译者:马东辉(eaststone ma_donghui@263.net)
译文发布时间:2001-4-4
版权:本中文翻译文档版权归中国互动出版网所有。可以用于非商业用途自由转载,但必须保留本文档的翻译及版权信息。
Network Working Group Sun Microsystems, Inc.
Request for Comments: 1094 March 1989
RFC1094 网络文件系统协议
(RFC1094 NFS: Network File System Protocol Specification)
本备忘录状态
This memo provides information for the Internet community. It does
not specify an Internet standard of any kind. Distribution of this
memo is unlimited.
版权声明
Copyright (C) The Internet Society (1999). All Rights Reserved.
摘要:
网络文件系统可以使访问远程机上的目录和文件象在本地机上一样方便。本文就是介绍网络文件系统协议规范的中文版。
目录
1. 简介 2
1.1 远程过程调用 2
1.2 外部数据描述 2
1.3 无状态服务器 3
2. NFS 协议定义 3
2.1 文件系统模型 3
2.2 服务器过程 4
2.3 基本数据类型 12
3. NFS实现中的问题 18
3.1 服务器/客户端 的关系 18
3.2 路径名解析 18
3.3 许可问题 19
3.4 RPC信息 19
3.4 XDR结构的尺寸 20
3.6 设置RPC的参数 20
附录A 安装协议定义 21
A.1. 简介 21
A.2 RPC信息 21
A.3 XDR结构的尺寸 21
A.4 基本数据类型 22
A.5. 服务器过程 23
作者地址 25
1. 简介
Sun的网络文件系统(NFS)协议提供了对网络中的共享文件进行透明的远程访问。NFS协议被设计为适合于不同的机器,操作系统,网络体系和传输协议。这种广泛的适应性是通过使用建立在外部数据描述(XDR)之上的远程过程调用(RPC)原语得到的。此协议的实现已经存在于从个人电脑到超级电脑等不同种类的机器之上,。
对安装协议的支持允许服务器分发远程访问优先级给一个受限制的客户集。它执行了操作系统特定的功能,以允许把远程目录树链接在本地的文件系统上。
1.1 远程过程调用
Sun的远程过程调用规范提供了一个面向过程的远程服务的接口。.每一个服务器都提供了一个包含着一组过程的“程序”。NFS就是一种这样的程序。主机地址,程序号和过程号的组合指定了一个远程过程。NFS的一个目标就是不需要它的下层提供任何特定级别的可靠性。所以,它潜在地可以被使用在许多下层的传输层协议之上,甚至在另一个远程过程调用实现之上。为了便于讨论,本文档的剩余部分假定NFS实现在Sun的RPC上层。
1.2 外部数据描述
外部数据描述(XDR)标准提供了一个在网络上描述数据类型的公用方法。NFS协议规范就是使用RPC数据描述语言撰写的。要想获得更多的信息,请参见RFC 1014 "XDR:外部数据描述标准"。尽管存在自动化的RPC/XDR编译器可以产生服务器和客户端的“桩”(stubs)。NFS也不需要使用它们。任何提供相同功能的软件都可以使用,如果编码完全相同的话,它也可以与其它的NFS实现进行互操作。
1.3 无状态服务器
NFS协议被希望尽可能无状态。也就是说,服务器应该不必保持关于它的客户端的任何协议状态信息,这是为了功能正确。在失败的事件发生的时候,无状态服务器比有状态服务器有着明显的优点。在无状态服务器中,客户端仅仅需要重发请求直到服务器响应;客户端甚至不需要知道服务器已经崩溃或者是网络临时故障。而有状态服务器的客户端要么需要检测服务器失败,并且在服务器恢复的时候重建服务器状态,要么使客户端操作失败。
这可能听起来不象是一个重要的问题,但是它在一些意想不到的情况下影响着协议。我们认为只要能写一个非常简易的服务器,不需要在崩溃后花费昂贵的代价恢复,即使在协议中多一些额外的复杂性也是值得的。注意:即使使用号称“可靠”的传输协议TCP的时候,客户端也必须能够处理当它们超时的时候再次打开连接所产生的服务的中断。因此,无状态协议实际上可以使这个实现简化。
另一方面,NFS处理文件、目录这样本身就有状态的对象。如果文件不保持它的内容没被接触过会有什么好处呢?这样做的目的就是在协议本身不引入任何额外的状态。固有的状态操作,诸如文件或者记录锁定和远程执行都作为分开的服务实现,在此不讨论。
简化恢复的基本方法就是尽可能的采取“幂等”操作(为了它们有被重复的潜力)。这个协议版本中的一些操作并不能达到这个目的;幸运的是,大多数操作(例如Read 和Write)是幂等的。而且,多数服务器失败发生在操作之间,而不是发生在收到操作和响应之间。最后,尽管实际上服务器的失败可能很少,但是在复杂的网络中,任何网络,路由器或者网桥的失败与服务器的失败都是很难区分的。
2. NFS 协议定义
服务器随着时间改变,服务器使用的协议也一样。RPC对每一个RPC请求都提供了一个版本号。RFC已经定义了NFS协议的两个版本。即使在第二版中,也有少部分过时的过程和参数,这将在以后的版本中被删除。NFS协议第三版的RPC当前正在准备之中。(译者注:这是相对此RFC文档发布的时间来讲的,此文档发表于1989,3)
2.1 文件系统模型
NFS假定文件系统是分层次的,除了最底层是文件,其它层次都是目录。在目录中的每一个条目(文件,目录,设备等)都有一个字符串名。不同的操作系统可能在目录树的深度或者使用的名字上有所限制,就象用不同的语义来描述“路径名”,它是在名字中把所有组成部分(目录和文件名)串联起来。一个“文件系统”就是在一个单一的服务器上(通常是一个磁盘或者物理分区)有一个指定的“根”的树。一些操作系统提供了“安装”操作使所有的文件系统出现在一棵单一的树上。而其它的操作系统保持着一个文件系统“森林”。文件是由无解释字节组成的无结构流。第三版的NFS使用更普遍的文件系统模型。
NFS一次只查询路径名中的一个组成部分。为什么不一次就得到整个路径名,返回一个文件句柄呢?这里有一些不这样做的原因。首先,路径名需要在路径的组成部分之间有分隔符。不同的操作系统使用不同的分隔符。我们可以定义一种网络上标准的路径表示法,但是每一个路径名在每一个终点上将必须进行语法分析和转换。其它的问题在第三节(NFS实现中的问题)里讨论。
尽管文件和目录在许多方面是相似的对象,但是读目录和读文件也需要不同的过程。这里提供了描述目录的网络标准格式。使用象上面相同的参数来确定一个过程,此过程在每次调用的时候只返回一个目录项。这种方法产生的问题就是效率不高。目录包含着许多目录项,远程调用要返回每一项将是非常缓慢的。
2.2 服务器过程
这个协议被定义为一组过程,这组过程具有用RPC语言(XDR语言在程序,版本,过程声明方面的扩展)定义的参数和结果。每一个过程功能的简要描述都应该提供足够允许实现的信息。2.3节详细地描述了基本数据类型。
在NFS协议中的所有过程都假定是同步的。当一个过程返回给客户端,客户可以假定此操作已经完成,与请求相关的任何数据现在在一个稳定的存储上。例如,客户端的WRITE请求可能导致服务器更新数据块,文件系统信息块(比如间接块),和文件属性信息(大小和修改时间)。当WRITE返回给客户端,客户端假定这个写操作是可靠的。甚至在服务器崩溃的情况下,它也能丢弃这些已经写的数据。这就是服务器无状态的一个非常重要的部分。 如果服务器等待来自远程请求的刷新数据,客户端必须保存这些请求, 以便在服务器崩溃的情况下再次发送这些请求。
/*
* 远程文件服务程序
*/
program NFS_PROGRAM {
version NFS_VERSION {
void NFSPROC_NULL(void) = 0;
attrstat NFSPROC_GETATTR(fhandle) = 1;
attrstat NFSPROC_SETATTR(sattrargs) = 2;
void NFSPROC_ROOT(void) = 3;
diropres NFSPROC_LOOKUP(diropargs) = 4;
readlinkres NFSPROC_READLINK(fhandle) = 5;
readres NFSPROC_READ(readargs) = 6;
void NFSPROC_WRITECACHE(void) = 7;
attrstat NFSPROC_WRITE(writeargs) = 8;
diropres NFSPROC_CREATE(createargs) = 9;
stat NFSPROC_REMOVE(diropargs) = 10;
stat NFSPROC_RENAME(renameargs) = 11;
stat NFSPROC_LINK(linkargs) = 12;
stat NFSPROC_SYMLINK(symlinkargs) = 13;
diropres NFSPROC_MKDIR(createargs) = 14;
stat NFSPROC_RMDIR(diropargs) = 15;
readdirres NFSPROC_READDIR(readdirargs) = 16;
statfsres NFSPROC_STATFS(fhandle) = 17;
} = 2;
} = 100003;
2.2.1 不做工作
void NFSPROC_NULL(void) = 0;
这个过程不做工作,在所有RPC服务中它可以用来允许服务器响应测试和定时。
2.2.2 获得文件属性
attrstat NFSPROC_GETATTR (fhandle) = 1;
如果响应状态是 NFS_OK,那么响应属性包含由输入fhandle指定的文件的属性。
2.2.3. 设置文件属性
struct sattrargs {
fhandle file;
sattr attributes;
};
attrstat NFSPROC_SETATTR (sattrargs) = 2;
"attributes"值参数包含着一些字段,这些字段要么是 -1,要么是 "file"的文件属性的一个新值。如果响应状态是NFS_OK,那么响应属性在"SETATTR"操作完成之后具有文件的属性。
注意: -1指示在 "attributes"中一个没有使用的字段,在协议的下一版本将修改。
2.2.4 获得文件系统的根
void NFSPROC_ROOT(void) = 3;
已经过时。这个过程不再使用,因为找到一个文件系统的根文件句柄需要在客户端和服务器之间移动路径名。为了正确的做到这一点,我们必须定义一个路径名网络标准描述。查询根文件句柄已经由MNTPROC_MNT过程来实现。(详细情况请参见附录A,“安装协议定义”)
2.2.5. 查询文件名
diropres NFSPROC_LOOKUP(diropargs) = 4;
如果响应"status"是NFS_OK,响应 "file"和响应 "attributes"是参数 "dir"给定的目录中的文件名的文件句柄和属性。
2.2.6 从符号链接读
union readlinkres switch (stat status) {
case NFS_OK:
path data;
default:
void;
};
readlinkres NFSPROC_READLINK(fhandle) = 5;
如果"status"的值是NFS_OK,响应 "data"是fhandle参数引用的文件的符号链接中的数据。
注意:因为NFS总是在客户端解析路径名,如果在不同的客户端或者服务器上使用不同的语义,那么在一个符号链接中的路径名可能有不同的含义(或者无意义)。
2.2.7 从文件中读
struct readargs {
fhandle file;
unsigned offset;
unsigned count;
unsigned totalcount;
};
union readres switch (stat status) {
case NFS_OK:
fattr attributes;
nfsdata data;
default:
void;
};
readres NFSPROC_READ(readargs) = 6;
在由 "file"给出的文件中,从“offset”字节偏移开始返回 "count"个字节的 "data"。 这个文件的第一个字节是偏移量0。在读操作发生后,文件属性从 "attributes"中返回。
注意:参数 "totalcount"没有使用,在协议的下一修订版中将删除。
2.2.8 写到缓冲区
void NFSPROC_WRITECACHE(void) = 7;
将在协议的下一修订版中使用。
2.2.9 写到文件
struct writeargs {
fhandle file;
unsigned beginoffset;
unsigned offset;
unsigned totalcount;
nfsdata data;
};
attrstat NFSPROC_WRITE(writeargs) = 8;
从 "file"开头偏移的 "offset"字节处开始写数据 "data"。文件的第一个字节是在偏移0的位置。如果响应状态 "status"是NFS_OK,那么在写操作完成后响应属性 "attributes"中包含着文件的属性。写操作是原子的,从这次"WRITE"中写入的数据不会与客户端的另一次"WRITE"写入的数据混合在一起。
注意:参数"beginoffset"和"totalcount"被忽略,在协议的下一修订版中将被删除。
2.2.10 创建文件
struct createargs {
diropargs where;
sattr attributes;
};
diropres NFSPROC_CREATE(createargs) = 9;
文件"name"创建在由 "dir"指定的目录中。新文件的初始属性由"attributes"决定。 NFS_OK的响应状态表明这个文件被创建。响应"file"和响应"attributes"是这个文件的文件句柄和属性。任何其它的响应状态 "status"都意味着此操作失败,没有文件被创建。
注意: 这个例程可以传递一个排它的创建标志,意味着“仅在文件不存在的时候创建这个文件”。
2.2.11 删除文件
stat NFSPROC_REMOVE(diropargs) = 10;
文件 "name"从 "dir"确定的目录中删除。NFS_OK的响应意味着这个目录项被删除。
注意:可能不是幂等地操作。
2.2.12 重命名文件
struct renameargs {
diropargs from;
diropargs to;
};
stat NFSPROC_RENAME(renameargs) = 11;
在"from.dir"目录中的"from.name"文件被更名为"to.dir"目录中的文件名"to.name"。如果响应是NFS_OK,文件被更名。更名操作在服务器上是一个原子操作;它不能在执行中被中断。
注意:可能不是幂等地操作。
2.2.13 创建文件链接
过程12,版本2。
struct linkargs {
fhandle from;
diropargs to;
};
stat NFSPROC_LINK(linkargs) = 12;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -