1.簡介
Sun的網(wǎng)絡(luò)文件系統(tǒng)(NFS)協(xié)議提供了對網(wǎng)絡(luò)中的共享文件進(jìn)行透明的遠(yuǎn)程訪問。NFS協(xié)議被設(shè)計(jì)為適合于不同的機(jī)器,操作系統(tǒng),網(wǎng)絡(luò)體系和傳輸協(xié)議。這種廣泛的適應(yīng)性是通過使用建立在外部數(shù)據(jù)描述(XDR)之上的遠(yuǎn)程過程調(diào)用(RPC)原語得到的。此協(xié)議的實(shí)現(xiàn)已經(jīng)存在于從個人電腦到超級電腦等不同種類的機(jī)器之上,。
對安裝協(xié)議的支持答應(yīng)服務(wù)器分發(fā)遠(yuǎn)程訪問優(yōu)先級給一個受限制的客戶集。它執(zhí)行了操作系統(tǒng)特定的功能,以答應(yīng)把遠(yuǎn)程目錄樹鏈接在本地的文件系統(tǒng)上。
1.1遠(yuǎn)程過程調(diào)用
Sun的遠(yuǎn)程過程調(diào)用規(guī)范提供了一個面向過程的遠(yuǎn)程服務(wù)的接口。.每一個服務(wù)器都提供了一個包含著一組過程的“程序”。NFS就是一種這樣的程序。主機(jī)地址,程序號和過程號的組合指定了一個遠(yuǎn)程過程。NFS的一個目標(biāo)就是不需要它的下層提供任何特定級別的可靠性。所以,它潛在地可以被使用在許多下層的傳輸層協(xié)議之上,甚至在另一個遠(yuǎn)程過程調(diào)用實(shí)現(xiàn)之上。為了便于討論,本文檔的剩余部分假定NFS實(shí)現(xiàn)在Sun的RPC上層。
1.2外部數(shù)據(jù)描述
外部數(shù)據(jù)描述(XDR)標(biāo)準(zhǔn)提供了一個在網(wǎng)絡(luò)上描述數(shù)據(jù)類型的公用方法。NFS協(xié)議規(guī)范就是使用RPC數(shù)據(jù)描述語言撰寫的。要想獲得更多的信息,請參見RFC1014"XDR:外部數(shù)據(jù)描述標(biāo)準(zhǔn)"。盡管存在自動化的RPC/XDR編譯器可以產(chǎn)生服務(wù)器和客戶端的“樁”(stubs)。NFS也不需要使用它們。任何提供相同功能的軟件都可以使用,假如編碼完全相同的話,它也可以與其它的NFS實(shí)現(xiàn)進(jìn)行互操作。
1.3無狀態(tài)服務(wù)器
NFS協(xié)議被希望盡可能無狀態(tài)。也就是說,服務(wù)器應(yīng)該不必保持關(guān)于它的客戶端的任何協(xié)議狀態(tài)信息,這是為了功能正確。在失敗的事件發(fā)生的時(shí)候,無狀態(tài)服務(wù)器比有狀態(tài)服務(wù)器有著明顯的優(yōu)點(diǎn)。在無狀態(tài)服務(wù)器中,客戶端僅僅需要重發(fā)請求直到服務(wù)器響應(yīng);客戶端甚至不需要知道服務(wù)器已經(jīng)崩潰或者是網(wǎng)絡(luò)臨時(shí)故障。而有狀態(tài)服務(wù)器的客戶端要么需要檢測服務(wù)器失敗,并且在服務(wù)器恢復(fù)的時(shí)候重建服務(wù)器狀態(tài),要么使客戶端操作失敗。
這可能聽起來不象是一個重要的問題,但是它在一些意想不到的情況下影響著協(xié)議。我們認(rèn)為只要能寫一個非常簡易的服務(wù)器,不需要在崩潰后花費(fèi)昂貴的代價(jià)恢復(fù),即使在協(xié)議中多一些額外的復(fù)雜性也是值得的。注重:即使使用號稱“可靠”的傳輸協(xié)議TCP的時(shí)候,客戶端也必須能夠處理當(dāng)它們超時(shí)的時(shí)候再次打開連接所產(chǎn)生的服務(wù)的中斷。因此,無狀態(tài)協(xié)議實(shí)際上可以使這個實(shí)現(xiàn)簡化。
另一方面,NFS處理文件、目錄這樣本身就有狀態(tài)的對象。假如文件不保持它的內(nèi)容沒被接觸過會有什么好處呢?這樣做的目的就是在協(xié)議本身不引入任何額外的狀態(tài)。固有的狀態(tài)操作,諸如文件或者記錄鎖定和遠(yuǎn)程執(zhí)行都作為分開的服務(wù)實(shí)現(xiàn),在此不討論。
簡化恢復(fù)的基本方法就是盡可能的采取“冪等”操作(為了它們有被重復(fù)的潛力)。這個協(xié)議版本中的一些操作并不能達(dá)到這個目的;幸運(yùn)的是,大多數(shù)操作(例如Read和Write)是冪等的。而且,多數(shù)服務(wù)器失敗發(fā)生在操作之間,而不是發(fā)生在收到操作和響應(yīng)之間。最后,盡管實(shí)際上服務(wù)器的失敗可能很少,但是在復(fù)雜的網(wǎng)絡(luò)中,任何網(wǎng)絡(luò),路由器或者網(wǎng)橋的失敗與服務(wù)器的失敗都是很難區(qū)分的。
2.NFS協(xié)議定義
服務(wù)器隨著時(shí)間改變,服務(wù)器使用的協(xié)議也一樣。RPC對每一個RPC請求都提供了一個版本號。RFC已經(jīng)定義了NFS協(xié)議的兩個版本。即使在第二版中,也有少部分過時(shí)的過程和參數(shù),這將在以后的版本中被刪除。NFS協(xié)議第三版的RPC當(dāng)前正在預(yù)備之中。(譯者注:這是相對此RFC文檔發(fā)布的時(shí)間來講的,此文檔發(fā)表于1989,3)
2.1文件系統(tǒng)模型
NFS假定文件系統(tǒng)是分層次的,除了最底層是文件,其它層次都是目錄。在目錄中的每一個條目(文件,目錄,設(shè)備等)都有一個字符串名。不同的操作系統(tǒng)可能在目錄樹的深度或者使用的名字上有所限制,就象用不同的語義來描述“路徑名”,它是在名字中把所有組成部分(目錄和文件名)串聯(lián)起來。一個“文件系統(tǒng)”就是在一個單一的服務(wù)器上(通常是一個磁盤或者物理分區(qū))有一個指定的“根”的樹。一些操作系統(tǒng)提供了“安裝”操作使所有的文件系統(tǒng)出現(xiàn)在一棵單一的樹上。而其它的操作系統(tǒng)保持著一個文件系統(tǒng)“森林”。文件是由無解釋字節(jié)組成的無結(jié)構(gòu)流。第三版的NFS使用更普遍的文件系統(tǒng)模型。
NFS一次只查詢路徑名中的一個組成部分。為什么不一次就得到整個路徑名,返回一個文件句柄呢?這里有一些不這樣做的原因。首先,路徑名需要在路徑的組成部分之間有分隔符。不同的操作系統(tǒng)使用不同的分隔符。我們可以定義一種網(wǎng)絡(luò)上標(biāo)準(zhǔn)的路徑表示法,但是每一個路徑名在每一個終點(diǎn)上將必須進(jìn)行語法分析和轉(zhuǎn)換。其它的問題在第三節(jié)(NFS實(shí)現(xiàn)中的問題)里討論。
盡管文件和目錄在許多方面是相似的對象,但是讀目錄和讀文件也需要不同的過程。這里提供了描述目錄的網(wǎng)絡(luò)標(biāo)準(zhǔn)格式。使用象上面相同的參數(shù)來確定一個過程,此過程在每次調(diào)用的時(shí)候只返回一個目錄項(xiàng)。這種方法產(chǎn)生的問題就是效率不高。目錄包含著許多目錄項(xiàng),遠(yuǎn)程調(diào)用要返回每一項(xiàng)將是非常緩慢的。
2.2服務(wù)器過程
這個協(xié)議被定義為一組過程,這組過程具有用RPC語言(XDR語言在程序,版本,過程聲明方面的擴(kuò)展)定義的參數(shù)和結(jié)果。每一個過程功能的簡要描述都應(yīng)該提供足夠答應(yīng)實(shí)現(xiàn)的信息。2.3節(jié)具體地描述了基本數(shù)據(jù)類型。
在NFS協(xié)議中的所有過程都假定是同步的。當(dāng)一個過程返回給客戶端,客戶可以假定此操作已經(jīng)完成,與請求相關(guān)的任何數(shù)據(jù)現(xiàn)在在一個穩(wěn)定的存儲上。例如,客戶端的WRITE請求可能導(dǎo)致服務(wù)器更新數(shù)據(jù)塊,文件系統(tǒng)信息塊(比如間接塊),和文件屬性信息(大小和修改時(shí)間)。當(dāng)WRITE返回給客戶端,客戶端假定這個寫操作是可靠的。甚至在服務(wù)器崩潰的情況下,它也能丟棄這些已經(jīng)寫的數(shù)據(jù)。這就是服務(wù)器無狀態(tài)的一個非常重要的部分。假如服務(wù)器等待來自遠(yuǎn)程請求的刷新數(shù)據(jù),客戶端必須保存這些請求,以便在服務(wù)器崩潰的情況下再次發(fā)送這些請求。
/*
*遠(yuǎn)程文件服務(wù)程序
*/
PRogramNFS_PROGRAM{
versionNFS_VERSION{
voidNFSPROC_NULL(void)=0;
attrstatNFSPROC_GETATTR(fhandle)=1;
attrstatNFSPROC_SETATTR(sattrargs)=2;
voidNFSPROC_ROOT(void)=3;
diropresNFSPROC_LOOKUP(diropargs)=4;
readlinkresNFSPROC_READLINK(fhandle)=5;
readresNFSPROC_READ(readargs)=6;
voidNFSPROC_WRITECACHE(void)=7;
attrstatNFSPROC_WRITE(writeargs)=8;
diropresNFSPROC_CREATE(createargs)=9;
statNFSPROC_REMOVE(diropargs)=10;
statNFSPROC_RENAME(renameargs)=11;
statNFSPROC_LINK(linkargs)=12;
statNFSPROC_SYMLINK(symlinkargs)=13;
diropresNFSPROC_MKDIR(createargs)=14;
statNFSPROC_RMDIR(diropargs)=15;
readdirresNFSPROC_READDIR(readdirargs)=16;
statfsresNFSPROC_STATFS(fhandle)=17;
}=2;
}=100003;
2.2.1不做工作
voidNFSPROC_NULL(void)=0;
這個過程不做工作,在所有RPC服務(wù)中它可以用來答應(yīng)服務(wù)器響應(yīng)測試和定時(shí)。
2.2.2獲得文件屬性
attrstatNFSPROC_GETATTR(fhandle)=1;
假如響應(yīng)狀態(tài)是NFS_OK,那么響應(yīng)屬性包含由輸入fhandle指定的文件的屬性。
2.2.3.設(shè)置文件屬性
strUCtsattrargs{
fhandlefile;
sattrattributes;
};
attrstatNFSPROC_SETATTR(sattrargs)=2;
"attributes"值參數(shù)包含著一些字段,這些字段要么是-1,要么是"file"的文件屬性的一個新值。假如響應(yīng)狀態(tài)是NFS_OK,那么響應(yīng)屬性在"SETATTR"操作完成之后具有文件的屬性。
注重:-1指示在"attributes"中一個沒有使用的字段,在協(xié)議的下一版本將修改。
2.2.4獲得文件系統(tǒng)的根
voidNFSPROC_ROOT(void)=3;
已經(jīng)過時(shí)。這個過程不再使用,因?yàn)檎业揭粋€文件系統(tǒng)的根文件句柄需要在客戶端和服務(wù)器之間移動路徑名。為了正確的做到這一點(diǎn),我們必須定義一個路徑名網(wǎng)絡(luò)標(biāo)準(zhǔn)描述。查詢根文件句柄已經(jīng)由MNTPROC_MNT過程來實(shí)現(xiàn)。(具體情況請參見附錄A,“安裝協(xié)議定義”)
2.2.5.查詢文件名
diropresNFSPROC_LOOKUP(diropargs)=4;
假如響應(yīng)"status"是NFS_OK,響應(yīng)"file"和響應(yīng)"attributes"是參數(shù)"dir"給定的目錄中的文件名的文件句柄和屬性。
2.2.6從符號鏈接讀
unionreadlinkresswitch(statstatus){
caseNFS_OK:
pathdata;
default:
void;
};
readlinkresNFSPROC_READLINK(fhandle)=5;
假如"status"的值是NFS_OK,響應(yīng)"data"是fhandle參數(shù)引用的文件的符號鏈接中的數(shù)據(jù)。
注重:因?yàn)镹FS總是在客戶端解析路徑名,假如在不同的客戶端或者服務(wù)器上使用不同的語義,那么在一個符號鏈接中的路徑名可能有不同的含義(或者無意義)。
2.2.7從文件中讀
structreadargs{
fhandlefile;
unsignedoffset;
unsignedcount;
unsignedtotalcount;
};
unionreadresswitch(statstatus){
caseNFS_OK:
fattrattributes;
nfsdatadata;
default:
void;
};
readresNFSPROC_READ(readargs)=6;
在由"file"給出的文件中,從“offset”字節(jié)偏移開始返回"count"個字節(jié)的"data"。這個文件的第一個字節(jié)是偏移量0。在讀操作發(fā)生后,文件屬性從"attributes"中返回。
注重:參數(shù)"totalcount"沒有使用,在協(xié)議的下一修訂版中將刪除。
2.2.8寫到緩沖區(qū)
voidNFSPROC_WRITECACHE(void)=7;
將在協(xié)議的下一修訂版中使用。
2.2.9寫到文件
structwriteargs{
fhandlefile;
unsignedbeginoffset;
unsignedoffset;
unsignedtotalcount;
nfsdatadata;
};
attrstatNFSPROC_WRITE(writeargs)=8;
從"file"開頭偏移的"offset"字節(jié)處開始寫數(shù)據(jù)"data"。文件的第一個字節(jié)是在偏移0的位置。假如響應(yīng)狀態(tài)"status"是NFS_OK,那么在寫操作完成后響應(yīng)屬性"attributes"中包含著文件的屬性。寫操作是原子的,從這次"WRITE"中寫入的數(shù)據(jù)不會與客戶端的另一次"WRITE"寫入的數(shù)據(jù)混合在一起。
注重:參數(shù)"beginoffset"和"totalcount"被忽略,在協(xié)議的下一修訂版中將被刪除。
2.2.10創(chuàng)建文件
structcreateargs{
diropargswhere;
sattrattributes;
};
diropresNFSPROC_CREATE(createargs)=9;
文件"name"創(chuàng)建在由"dir"指定的目錄中。新文件的初始屬性由"attributes"決定。NFS_OK的響應(yīng)狀態(tài)表明這個文件被創(chuàng)建。響應(yīng)"file"和響應(yīng)"attributes"是這個文件的文件句柄和屬性。任何其它的響應(yīng)狀態(tài)"status"都意味著此操作失敗,沒有文件被創(chuàng)建。
注重:這個例程可以傳遞一個排它的創(chuàng)建標(biāo)志,意味著“僅在文件不存在的時(shí)候創(chuàng)建這個文件”。
2.2.11刪除文件
statNFSPROC_REMOVE(diropargs)=10;
文件"name"從"dir"確定的目錄中刪除。NFS_OK的響應(yīng)意味著這個目錄項(xiàng)被刪除。
注重:可能不是冪等地操作。
2.2.12重命名文件
structrenameargs{
diropargsfrom;
diropargsto;
};
statNFSPROC_RENAME(renameargs)=11;
在"from.dir"目錄中的"from.name"文件被更名為"to.dir"目錄中的文件名"to.name"。假如響應(yīng)是NFS_OK,文件被更名。更名操作在服務(wù)器上是一個原子操作;它不能在執(zhí)行中被中斷。
注重:可能不是冪等地操作。
2.2.13創(chuàng)建文件鏈接
過程12,版本2。
structlinkargs{
fhandlefrom;
diropargsto;
};
statNFSPROC_LINK(linkargs)=12;
在"to.dir"目錄中創(chuàng)建文件"to.name",它是已存在的文件"from"的一個硬鏈接。假如返回值是NFS_OK,一個鏈接創(chuàng)立。如何返回其它的值表明出錯,這個鏈接沒有創(chuàng)建。
硬鏈接應(yīng)該具有這樣的屬性,鏈接的文件中的任何一個改變都將影響到兩個文件。當(dāng)硬鏈接指向一個文件的時(shí)候,文件屬性中應(yīng)該有一個表示"nlink"的值,這個值比鏈接前大。
注重:可能不是冪等地操作。
2.2.14創(chuàng)建符號鏈接
structsymlinkargs{
diropargsfrom;
pathto;
sattrattributes;
};
statNFSPROC_SYMLINK(symlinkargs)=13;
在給定的目錄"from.dir"中創(chuàng)建一個文件類型是NFLNK的文件"from.name"。這個新文件包含著路徑名"to",具有"attributes"指定的初始屬性。假如返回值是NFS_OK,一個鏈接被創(chuàng)建。任何其它的返回值指示錯誤,鏈接沒有創(chuàng)建。
符號鏈接是指向另一個文件的指針。在"to"中給定的名字不被服務(wù)器解釋,只存儲在新建的文件中。當(dāng)客戶端引用一個符號鏈接文件的時(shí)候,符號鏈接中的內(nèi)容通常作為一個代替的路徑名重新被解釋。READLINK的操作返回給客戶端要解釋的數(shù)據(jù)。
注重:在UNIX服務(wù)器上,attributes從不使用,因?yàn)榉栨溄涌偸蔷哂?777的模式。
2.2.15創(chuàng)建目錄
diropresNFSPROC_MKDIR(createargs)=14;
新目錄"where.name"創(chuàng)建在給定的目錄"where.dir"中。新目錄的初始屬性由"attributes"確定。一個NFS_OK的返回值表示新目錄被創(chuàng)建,響應(yīng)"file"和響應(yīng)"attributes"是這個新目錄的文件句柄和屬性。返回任何其它的響應(yīng)狀態(tài)"status"都意味著操作失敗,沒有目錄被創(chuàng)建。
注重:可能不是冪等地操作。
2.2.16刪除目錄
statNFSPROC_RMDIR(diropargs)=15;
在"dir"指定的目錄中的空的目錄"name"將被刪除,假如響應(yīng)是NFS_OK,目錄被刪除。
注重:可能不是冪等地操作。
2.2.17從目錄中讀
structreaddirargs{
fhandledir;
nfscookiecookie;
unsignedcount;
};
structentry{
unsignedfileid;
filenamename;
nfscookiecookie;
entry*nextentry;
};
unionreaddirresswitch(statstatus){
caseNFS_OK:
struct{
entry*entries;
booleof;
}readdirok;
default:
void;
};
readdirresNFSPROC_READDIR(readdirargs)=16;
從"dir"指定的目錄中返回一個可變數(shù)目的目錄項(xiàng)集合,總的大小是"count"個字節(jié)。假如返回的狀態(tài)值"status"是NFS_OK,那么后跟一組可變數(shù)目的"entry"。每一個"entry"包含著一個"fileid",這個"fileid"是由文件系統(tǒng)中唯一標(biāo)識這個文件的號碼,文件名和一個指向目錄中下一個目錄項(xiàng)的不透明指針"cookie"組成。Cookie使用在下面的READDIR調(diào)用中,以便在這個目錄中從一個指定的開始點(diǎn)獲得更多的目錄項(xiàng)。非凡的cookie值0(所有比特都是0)使得從目錄的開始點(diǎn)得到目錄項(xiàng)。"fileid"字段應(yīng)該和在文件屬性中的"fileid"字段中有同樣的值。(見“基本數(shù)據(jù)類型”中的2.3.5節(jié)“fattr”)假如在目錄中沒有更多的目錄項(xiàng),"eof"標(biāo)志的值是TRUE。
2.2.18獲得文件系統(tǒng)屬性
unionstatfsres(statstatus){
caseNFS_OK:
struct{
unsignedtsize;
unsignedbsize;
unsignedblocks;
unsignedbfree;
unsignedbavail;
}info;
default:
void;
};
statfsresNFSPROC_STATFS(fhandle)=17;
假如響應(yīng)狀態(tài)"status"是NFS_OK,那么響應(yīng)"info"給出包含著由輸入文件句柄fhandle引用的文件的文件系統(tǒng)的屬性。屬性字段包含著下列值:
tsize用字節(jié)表示的最優(yōu)化的傳輸尺寸。這是服務(wù)器在READ和WRITE請求中的
最想要的數(shù)據(jù)字節(jié)數(shù)。
bsize文件系統(tǒng)用字節(jié)表示的塊尺寸。.
blocks文件系統(tǒng)中"bsize"塊的總數(shù)。
bfree文件系統(tǒng)中自由的“bsize”塊的數(shù)目。
bavail無特權(quán)用戶可用的"bsize"塊的數(shù)目。
注重:假如文件系統(tǒng)具有可變尺寸的塊,這個調(diào)用不能很好的工作。
2.3基本數(shù)據(jù)類型
以下XDR定義是在描述其它結(jié)構(gòu)中使用的基本的結(jié)構(gòu)和類型。
2.3.1.stat(統(tǒng)計(jì)類型)
enumstat{
NFS_OK=0,
NFSERR_PERM=1,
NFSERR_NOENT=2,
NFSERR_IO=5,
NFSERR_NXIO=6,
NFSERR_ACCES=13,
NFSERR_EXIST=17,
NFSERR_NODEV=19,
NFSERR_NOTDIR=20,
NFSERR_ISDIR=21,
NFSERR_FBIG=27,
NFSERR_NOSPC=28,
NFSERR_ROFS=30,
NFSERR_NAMETOOLONG=63,
NFSERR_NOTEMPTY=66,
NFSERR_DQUOT=69,
NFSERR_STALE=70,
NFSERR_WFLUSH=99
};
在每一個過程調(diào)用結(jié)果中都有統(tǒng)計(jì)類型"stat"被返回。NFS_OK的值表示調(diào)用執(zhí)行成功,結(jié)果有效。其它值表示服務(wù)器一側(cè)在過程服務(wù)中產(chǎn)生的某種錯誤。這些錯誤值來源于UNIX錯誤號。
NFSERR_PERM
不是所有者,調(diào)用者不是所請求操作的正確的所有者。
NFSERR_NOENT
不存在這樣的文件或者目錄。指定的文件或者目錄不存在。
NFSERR_IO
在操作執(zhí)行的時(shí)候出現(xiàn)某種硬件錯誤。例如,這可能是一個磁盤錯誤。
NFSERR_NXIO
沒有這樣的設(shè)備或者地址。
NFSERR_ACCES
許可權(quán)限拒絕。調(diào)用者沒有執(zhí)行請求操作的正確的權(quán)限。
NFSERR_EXIST
文件存在。指定的文件已經(jīng)存在。
NFSERR_NODEV
沒有這樣的設(shè)備。
NFSERR_NOTDIR
不是一個目錄。在目錄操作中調(diào)用者指定一個非目錄。
NFSERR_ISDIR
是一個目錄。調(diào)用者在一個非目錄操作中指定一個目錄。
NFSERR_FBIG
文件太大。操作造成文件增長超過服務(wù)器的限制。
NFSERR_NOSPC
在設(shè)備上沒有剩余的空間。這個操作導(dǎo)致服務(wù)器文件系統(tǒng)達(dá)到它的極限。
NFSERR_ROFS
只讀文件系統(tǒng)。在一個只讀文件系統(tǒng)上試圖寫。
NFSERR_NAMETOOLONG
文件名太長。在操作中文件名太長。
NFSERR_NOTEMPTY
目錄不空。試圖刪除一個不空的目錄。
NFSERR_DQUOT
磁盤限額超出。客戶在服務(wù)器上的磁盤限額已經(jīng)超出。
NFSERR_STALE
在參數(shù)中給的文件句柄"fhandle"無效。也就是說,這個文件句柄引用的文件不再存在。
或者訪問它的設(shè)置已經(jīng)被撤銷。
NFSERR_WFLUSH
使用"WRITECACHE"調(diào)用中的服務(wù)器寫緩沖區(qū)得到磁盤刷新。
2.3.2.ftype(文件類型)
enumftype{
NFNON=0,
NFREG=1,
NFDIR=2,
NFBLK=3,
NFCHR=4,
NFLNK=5
};
枚舉"ftype"類型給出文件的類型。NFNON類型表示不是一個文件,NFREG表示一個正常的文件,NFDIR表示一個目錄。NFBLK表示一個特定的塊設(shè)備,NFCHR表示一個特定的字符設(shè)備,NFLNK表示一個符號鏈接。
2.3.3.fhandle(文件句柄)
typedefopaquefhandle[FHSIZE];
"fhandle"是一個在服務(wù)器和客戶端之間傳送的文件句柄。所有文件操作都使用文件句柄來引用一個文件或者目錄。文件句柄包含著服務(wù)器需要的區(qū)分一個單獨(dú)文件的信息。
2.3.4.timeval(時(shí)間值)
structtimeval{
unsignedintseconds;
unsignedintuseconds;
};
"timeval"結(jié)構(gòu)是一個秒和微秒的數(shù)值,從格林威治時(shí)間1970年一月一日凌晨起計(jì)時(shí)。它使用在傳遞時(shí)間和日期的信息中。
2.3.5.fattr(文件屬性)
structfattr{
ftypetype;
unsignedintmode;
unsignedintnlink;
unsignedintuid;
unsignedintgid;
unsignedintsize;
unsignedintblocksize;
unsignedintrdev;
unsignedintblocks;
unsignedintfsid;
unsignedintfileid;
timevalatime;
timevalmtime;
timevalctime;
};
"fattr"結(jié)構(gòu)包含著文件的屬性;"type"是文件的類型;"nlink"是一個文件的硬鏈接數(shù)(對同一個文件不同的名字的數(shù)目);"uid"是這個文件的所有者的用戶標(biāo)識號碼;"gid"是擁有這個文件的組的組標(biāo)識號碼;"size"是這個文件以字節(jié)數(shù)計(jì)算的大小;"blocksize"是這個文件的一個塊以字節(jié)計(jì)數(shù)的大小;假如文件的類型是NFCHR或者NFBLK,"rdev"是這個文件的設(shè)備號;"blocks"是文件在磁盤上塊的數(shù)量;"fsid"是包含這個文件的文件系統(tǒng)的系統(tǒng)標(biāo)識符;"fileid"是這個文件在它的文件系統(tǒng)中唯一的標(biāo)識符號碼;"atime"是上次文件讀訪問或者寫訪問的時(shí)間;"mtime"是文件數(shù)據(jù)上次被修改時(shí)的時(shí)間(寫);"ctime"是文件狀態(tài)上次改變的時(shí)間。假如文件的尺寸改變,寫一個文件也將改變"ctime"。
"Mode"是被編碼成一個比特集合的訪問模式。注重文件類型要么在模式比特中指定,要么在文件類型中指定。這實(shí)際上是此協(xié)議中的一個缺陷,將在未來的版本中修訂。下面的描述使用八進(jìn)制數(shù)確定比特的位置
0040000這是一個目錄,"type"字段應(yīng)該是NFDIR。
0020000這是一個字符非凡文件,"type"字段應(yīng)該是NFCHR。
0060000這是一個塊非凡文件,"type"字段應(yīng)該是NFBLK。
0100000這是一個正常的文件,"type"字段應(yīng)該是NFREG。
0120000這是一個符號鏈接文件,"type"字段應(yīng)該是NFLNK。
0140000這是一個命名的socket;"type"字段應(yīng)該是NFNON。
0004000設(shè)置在執(zhí)行中的用戶ID
0002000設(shè)置在執(zhí)行中的組ID
0001000在使用后保存交換文本。
0000400對所有者的讀權(quán)限許可。
0000200對所有者的寫權(quán)限許可。
0000100對所有者的執(zhí)行和搜索權(quán)限許可。
0000040對組的讀權(quán)限許可。
0000020對組的寫權(quán)限許可。
0000010對組的執(zhí)行和搜索權(quán)限許可。
0000004對其他人的讀權(quán)限許可。
0000002對其他人的寫權(quán)限許可。
0000001對其他人的執(zhí)行和搜索權(quán)限許可。
注重:這些比特與UNIX中stat(2)系統(tǒng)調(diào)用中返回的模式比特是一樣的。文件類型要
么在模式比特中要么在文件類型中確定。這在未來的版本中將修改。
在屬性結(jié)構(gòu)中"rdev"字段是一個操作系統(tǒng)特定設(shè)備的標(biāo)識符。在這個協(xié)議的下一個
修訂版中將刪除。
2.3.6.sattr(設(shè)置文件屬性)
structsattr{
unsignedintmode;
unsignedintuid;
unsignedintgid;
unsignedintsize;
timevalatime;
timevalmtime;
};
"sattr"結(jié)構(gòu)包含著可以從客戶端設(shè)置的文件的屬性。這些字段與上面的"fattr"中的字段的含義是相同的。"size"值為0意味著文件將被截短。一個-1的值意味著這個字段將被忽略。
2.3.7.filename(文件名)
typedefstringfilename<MAXNAMLEN>;
"filename"用來傳送文件名或者路徑名的組成部分。
2.3.8.path(路徑)
typedefstringpath<MAXPATHLEN>;
"path"是一個路徑名。服務(wù)器把它作為一個沒有內(nèi)部結(jié)構(gòu)的字符串,但是對客戶端來說它是文件系統(tǒng)樹中的節(jié)點(diǎn)的名字。
2.3.9.attrstat(屬性狀態(tài))
unionattrstatswitch(statstatus){
caseNFS_OK:
fattrattributes;
default:
void;
};
"attrstat"結(jié)構(gòu)是一個公共的過程結(jié)果。它包含著一個"status",假如這個調(diào)用成功,它將也包含操作作用于那個文件的屬性。
2.3.10.diropargs(目錄操作參數(shù))
structdiropargs{
fhandledir;
filenamename;
};
"diropargs"結(jié)構(gòu)使用在目錄屬性操作中。"dir"是在其中尋找文件"name"的那個目錄。一個目錄操作影響這個目錄。
2.3.11.diropres(目錄操作結(jié)果)
uniondiropresswitch(statstatus){
caseNFS_OK:
struct{
fhandlefile;
fattrattributes;
}diropok;
default:
void;
};
在"diropres"中返回目錄操作的結(jié)果。假如這個調(diào)用成功,與這個文件相關(guān)的新文件句柄"file"和文件屬性"attributes"將連同"status"一起返回。
3.NFS實(shí)現(xiàn)中的問題
NFS協(xié)議設(shè)計(jì)為答應(yīng)不同的操作系統(tǒng)共享文件。但是,因?yàn)樗赨NIX環(huán)境中設(shè)計(jì),所以,許多操作與UNIX文件系統(tǒng)的操作語義相似。這一節(jié)討論實(shí)現(xiàn)中非凡的細(xì)節(jié)和語義的問題。
3.1服務(wù)器/客戶端的關(guān)系
NFS協(xié)議被設(shè)計(jì)為讓服務(wù)器盡可能的簡單和通用。有時(shí)候假如客戶端想實(shí)現(xiàn)復(fù)雜的文件系統(tǒng)語義,服務(wù)器的簡單性可能是一個難題。
例如,一些操作系統(tǒng)答應(yīng)刪除打開的文件。一個進(jìn)程能夠打開文件,當(dāng)文件打開的時(shí)候,從目錄中刪除它。只要進(jìn)程保持文件打開,這個文件就可以被讀寫,即使這個文件在文件系統(tǒng)中沒有名字。對于無狀態(tài)服務(wù)器來說,實(shí)現(xiàn)這些語義是不可能的。客戶端可以使用一些技巧,諸如在刪除時(shí)重命名這個文件,只在它關(guān)閉的時(shí)候刪除它。我們相信服務(wù)器提供了足夠的功能在客戶端上實(shí)現(xiàn)大多數(shù)文件系統(tǒng)的語義。
每一個NFS客戶端也是一個潛在的服務(wù)器,遠(yuǎn)程和本地安裝的文件系統(tǒng)可以自由的混合在一起。當(dāng)客戶端瀏覽遠(yuǎn)程文件系統(tǒng)的目錄樹,到達(dá)在服務(wù)器上另一個遠(yuǎn)程系統(tǒng)的安裝點(diǎn)的時(shí)候,將會出現(xiàn)一些有趣的問題。要答應(yīng)服務(wù)器跟隨第二個遠(yuǎn)程安裝就需要循環(huán)檢測,服務(wù)器查找和用戶重新生效。代替的做法是,我們決定不讓客戶端越過服務(wù)器的安裝點(diǎn)。.當(dāng)客戶端在一個服務(wù)器已經(jīng)安裝了文件系統(tǒng)的目錄中查詢的時(shí)候,客戶端將看見下面的目錄而不是安裝的目錄。
例如,假如服務(wù)器有一個叫做"/usr"的文件系統(tǒng),把另一個文件系統(tǒng)安裝在"/usr/src"上,假如客戶端安裝了"/usr",它將看不到"/usr/src"的安裝版本。客戶端能做遠(yuǎn)程安裝以配合服務(wù)器的安裝點(diǎn)保持服務(wù)器的視圖。在這個例子中,客戶端應(yīng)該除了安裝"/usr"之外,還要安裝"/usr/src",即使它們是來自同一臺服務(wù)器。
3.2路徑名解析
路徑名總是在客戶端解析的規(guī)則有點(diǎn)復(fù)雜。例如,符號鏈接在不同的客戶端可以有不同的解釋。對于非UNIX實(shí)現(xiàn)的另一個共同的問題就是路徑".."的專門的解釋是給定的目錄的父目錄。此協(xié)議的下一個修訂版將使用一個明確的標(biāo)志指示父目錄。
3.3許可問題
嚴(yán)格的講,NFS協(xié)議沒有定義服務(wù)器使用的許可權(quán)限檢查。但是,也希望使用AUTH_UNIX類型認(rèn)證這一基礎(chǔ)的保護(hù)機(jī)制作正常的操作系統(tǒng)許可權(quán)限檢查,服務(wù)器得到客戶的有效"uid",有效"gid"和每次調(diào)用上的組,使用它們來檢查許可。使用這種方法產(chǎn)生的問題可以用一些有趣的途徑來解決。
使用"uid"和"gid"暗示著客戶端和服務(wù)器分享相同的"uid"列表。每一對服務(wù)器和客戶端必須有相同的用戶到"uid",組到"gid"的映射。因?yàn)槊恳粋€客戶端也可能是一臺服務(wù)器,這意味著整個網(wǎng)絡(luò)共享相同的"uid/gid"空間。AUTH_DES(和NFS協(xié)議的下一個修訂版)使用字符串來代替數(shù)字,但是仍有復(fù)雜的問題要解決。
由于打開操作有狀態(tài),所以產(chǎn)生了另一個問題。大多數(shù)操作系統(tǒng)在打開文件的時(shí)候檢查許可權(quán)限,在每一次讀寫請求的時(shí)候檢查文件是否打開。在無狀態(tài)的服務(wù)器中,服務(wù)器沒有辦法知道文件是否打開,必須在每次讀寫調(diào)用的時(shí)候檢查許可權(quán)限。在一個本地文件系統(tǒng)上,用戶可以打開文件,然后改變權(quán)限不答應(yīng)別人接觸它,但是仍然能夠?qū)懳募驗(yàn)槲募谴蜷_的。相反,在遠(yuǎn)程文件系統(tǒng)上,寫操作將失敗。為了避免這種問題,服務(wù)器的許可檢查算法將答應(yīng)文件的所有者訪問文件,而不管許可的設(shè)置。
在從網(wǎng)絡(luò)中的文件上進(jìn)行頁面調(diào)度的時(shí)候,也會出現(xiàn)相似的問題。操作系統(tǒng)在打開一個文件進(jìn)行頁面調(diào)度之前,總是檢查執(zhí)行許可權(quán)限,然后從打開的文件中讀取塊。文件可能沒有讀許可權(quán)限,但是在文件打開后,這就不是一個問題了。NFS服務(wù)器不能區(qū)分在正常文件讀和頁面調(diào)入請求讀之間的區(qū)別。為了使這個可以工作,假如在調(diào)用中被給的"uid"在文件上有執(zhí)行或者讀許可權(quán)限,服務(wù)器將答應(yīng)讀文件。
在大多數(shù)操作系統(tǒng)中,一個非凡的用戶(在UNIX上,用戶ID為0)有訪問所有文件的權(quán)限,而不管文件中的所有權(quán)和設(shè)定的許可權(quán)限。"super-user"權(quán)限在服務(wù)器上不可能被答應(yīng),因?yàn)樵谧约汗ぷ髡旧系娜魏尉哂谐売脩魴?quán)限的人都能訪問所有的遠(yuǎn)程文件。UNIX服務(wù)器在訪問檢查前,默認(rèn)把用戶ID0映射為-2。這個工作在NFS的根文件系統(tǒng)中例外,在那里超級用戶訪問不能避免。
3.4RPC信息
認(rèn)證
NFS服務(wù)使用AUTH_UNIX,AUTH_DES或者AUTH_SHORT類型的認(rèn)證,
在NULL過程中例外,在那里AUTH_NONE也被答應(yīng)。
傳輸協(xié)議
NFS通常由UDP支持。
端口號
NFS協(xié)議當(dāng)前使用UDP端口號2049。這不是一個正式分配的端口號,所以,
這個協(xié)議的后繼版本使用RPC的“端口映射”工具。
3.4XDR結(jié)構(gòu)的尺寸
這里有一些使用在此協(xié)議中不同的XDR結(jié)構(gòu)的尺寸,用十進(jìn)制字節(jié)給出。
/*
*在讀寫請求中的數(shù)據(jù)的最大字節(jié)數(shù)。
*/
constMAXDATA=8192;
/*在路徑參數(shù)中的最大字節(jié)數(shù)*/
constMAXPATHLEN=1024;
/*在文件名參數(shù)中的最大字節(jié)數(shù)*/
constMAXNAMLEN=255;
/*被READDIR傳送的"cookie"字節(jié)數(shù)的大小*/
constCOOKIESIZE=4;
/*不透明文件句柄的字節(jié)數(shù)的大小*/
constFHSIZE=32;
3.6設(shè)置RPC的參數(shù)
不同的文件系統(tǒng)參數(shù)和選項(xiàng)應(yīng)該在安裝的時(shí)候設(shè)置。安裝協(xié)議在附錄中描述。例如,象“硬”安裝一樣,“軟”安裝也被提供。當(dāng)RPC操作失敗(在給出一個重傳的選項(xiàng)號后),軟安裝文件系統(tǒng)返回錯誤,而硬安裝文件系統(tǒng)一直繼續(xù)重傳。最大的傳輸尺寸依靠于實(shí)現(xiàn)。對于在一個本地網(wǎng)的有效操作來說,通常使用8192字節(jié)的數(shù)據(jù)。這可能導(dǎo)致下層的分段(諸如在ip層)。既然一些網(wǎng)絡(luò)接口不答應(yīng)這樣的包,對于在低速網(wǎng)絡(luò)、主機(jī)上的操作,或者通過網(wǎng)關(guān)的操作,512或1024字節(jié)總是提供較好的結(jié)果。
客戶機(jī)和服務(wù)器可能需要把當(dāng)前的操作保存在緩沖區(qū)中,以幫助避免因?yàn)榉莾绲鹊牟僮鳟a(chǎn)生的問題。例如,假如傳輸協(xié)議丟失了刪除文件操作的響應(yīng),在重傳的時(shí)候,服務(wù)器可能返回一個NFSERR_NOENT來代替NFS_OK。但是,假如服務(wù)器保持上次的請求操作和結(jié)果,它可能返回正確的成功的代碼。當(dāng)然,服務(wù)器在重傳之間可能崩潰、重起。但是一塊很小的緩沖區(qū)(甚至只是容納一個條目)將解決大部分的問題。
附錄A安裝協(xié)議定義
A.1.簡介
安裝協(xié)議與NFS協(xié)議分離,但是與NFS協(xié)議相關(guān)。它提供了操作系統(tǒng)特定的服務(wù)來擴(kuò)展NFS的功能:查詢服務(wù)器路徑名,使用戶身份有效,檢查訪問權(quán)限。客戶端使用安裝協(xié)議得到第一個文件句柄,這答應(yīng)客戶進(jìn)入一個遠(yuǎn)程的文件系統(tǒng)。
安裝協(xié)議與NFS協(xié)議保持分離,使得在不改變NFS服務(wù)器協(xié)議的情況下很輕易加進(jìn)新的訪問檢查和確認(rèn)的方法。
注重:這個協(xié)議的定義暗示著服務(wù)器有狀態(tài),因?yàn)榉?wù)器保持著一個客戶端安裝請求的列表。安裝列表信息對客戶機(jī)或者服務(wù)器的功能沒有危害性。僅僅建議在服務(wù)器出現(xiàn)故障時(shí),給客戶機(jī)可能的警告。
安裝協(xié)議的第一版與NFS協(xié)議的第二版一起使用,在兩個協(xié)議中唯一通信的信息是"fhandle"結(jié)構(gòu)。
A.2RPC信息
認(rèn)證
安裝服務(wù)僅使用AUTH_UNIX和AUTH_NONE類型的認(rèn)證
傳輸協(xié)議
安裝服務(wù)被UDP和TCP中支持。
端口號
與服務(wù)器的端口映射器協(xié)商,來發(fā)現(xiàn)安裝服務(wù)注冊的端口號。
A.3XDR結(jié)構(gòu)的尺寸
這里有使用在此協(xié)議中不同的XDR結(jié)構(gòu)的尺寸,用十進(jìn)制表示。
/*路徑名參數(shù)的最大字節(jié)數(shù)*/
constMNTPATHLEN=1024;
/*一個名字參數(shù)的最大字節(jié)數(shù)*/
constMNTNAMLEN=255;
/*不透明文件句柄的字節(jié)數(shù)*/
constFHSIZE=32;
A.4基本數(shù)據(jù)類型
這一節(jié)描述使用在安裝協(xié)議中的數(shù)據(jù)類型。在許多情況下它們與使用在NFS中的數(shù)據(jù)類型相似。
A.4.1.fhandle
typedefopaquefhandle[FHSIZE];
"fhandle"類型是服務(wù)器傳遞給客戶端的文件句柄。所有文件操作都使用文件句柄來引用文件或者目錄。文件句柄包含著服務(wù)器需要的區(qū)分單個文件的信息。
這與NFS協(xié)議第二版中的"fhandle"XDR定義一樣;見在"基本數(shù)據(jù)類型"之中的"2.3.3.fhandle"。
A.4.2.fhstatus
unionfhstatusswitch(unsignedstatus){
case0:
fhandleDirectory;
default:
void;
}
"fhstatus"類型是一個聯(lián)合結(jié)構(gòu)。假如返回的"status"為0,調(diào)用執(zhí)行成功,接著的是給"directory"分配的文件句柄。一個非0值表示一些種類的錯誤。在這種情況下,status是一個UNIX錯誤號。
A.4.3.dirpath
typedefstringdirpath<MNTPATHLEN>;
"dirpath"類型是一個目錄的服務(wù)器的路徑名。
A.4.4.name
typedefstringname<MNTNAMLEN>;
"name"類型是一個使用在不同名字中的二進(jìn)制串。
A.5.服務(wù)器過程
下面的部分定義了安裝服務(wù)器提供的RPC過程。
/*
*安裝程序的協(xié)議定義
*/
programMOUNTPROG{
/*
*安裝協(xié)議的第一版與NFS協(xié)議的第二版使用在一起。
*/
versionMOUNTVERS{
voidMOUNTPROC_NULL(void)=0;
fhstatusMOUNTPROC_MNT(dirpath)=1;
mountlistMOUNTPROC_DUMP(void)=2;
voidMOUNTPROC_UMNT(dirpath)=3;
voidMOUNTPROC_UMNTALL(void)=4;
exportlistMOUNTPROC_EXPORT(void)=5;
}=1;
}=100005;
A.5.1.不作工作
voidMNTPROC_NULL(void)=0;
這個過程什么也不作,在所有的RPC服務(wù)中使用它來答應(yīng)服務(wù)器響應(yīng)測試和定時(shí)。
A.5.2加入安裝條目
fhstatusMNTPROC_MNT(dirpath)=1;
假如響應(yīng)狀態(tài)"status"是0,那么響應(yīng)的"directory"包含著目錄"dirname"的文件句柄。這個文件句柄可能使用在NFS協(xié)議中。這個過程也在客戶安裝的"dirname"安裝列表中加一個新的項(xiàng)目。
A.5.3返回安裝條目
struct*mountlist{
namehostname;
dirpathdirectory;
mountlistnextentry;
};
mountlistMNTPROC_DUMP(void)=2;
返回一個遠(yuǎn)程安裝文件系統(tǒng)的列表。"mountlist"對每一對"hostname"和"directory"都包含著一個條目。
A.5.4.刪除安裝條目
voidMNTPROC_UMNT(dirpath)=3;
從輸入"dirpath"中刪除安裝列表?xiàng)l目
A.5.5.刪除所有的安裝條目
voidMNTPROC_UMNTALL(void)=4;
為客戶端刪除所有安裝列表的條目
A.5.6.返回輸出列表
struct*groups{
namegrname;
groupsgrnext;
};
struct*exportlist{
dirpathfilesys;
groupsgroups;
exportlistnext;
};
exportlistMNTPROC_EXPORT(void)=5;
返回一組可變數(shù)目的輸出列表?xiàng)l目。每一個條目包含著文件系統(tǒng)名和一個被答應(yīng)導(dǎo)入的組列表。文件系統(tǒng)名在"filesys"當(dāng)中,組名在列表"groups"中。
注重:輸出列表應(yīng)該包含關(guān)于文件系統(tǒng)狀態(tài)的更多的信息,例如只讀標(biāo)志。
作者地址
BillNowicki
SunMicrosystems,Inc.
MailStop1-40
2550GarciaAvenue
MountainView,CA94043
Phone:(415)336-7278
Email:nowicki@SUN.COM
新聞熱點(diǎn)
疑難解答
圖片精選