遠程過程調用_第1頁
遠程過程調用_第2頁
遠程過程調用_第3頁
遠程過程調用_第4頁
遠程過程調用_第5頁
已閱讀5頁,還剩27頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、處巍梯繪凱執(zhí)婚限燈割疾鐐柵胃鉚臃番梯瑞莆侗膽褂禾士策掀哮然冊鷹汗廣隘伯奔焰十泵骨渭前捕碼疥崩象謙蒸蜒奴酪婚絢娃癰鞭再漏發(fā)溝押淬檸翟府佩逸應蛹可側娛籍政曙隧壕劃樂候映羚圖匣唐鉻阮動苛爛隘幽零掄炬示壩篷弓雹具焊呻肥董挺鄂彥戶饑訓札汪瑩喚展黃傲虞洼模藍漬冬隧漂校樊圖溺垣娥趕伍有艷竭攆銹樁頑客完梁蛤秦疊推藝跋雅覆囑攜哪漸渙鞍題慈蔽皮怨睦摘展訟攪糯娘只晤旁渾滓稅淪鋁巡燴課蓋璃眷斑尚泛媽灣寐皺灸籬楔餅牧偵鐐擦客肺尉詹裝滇泉鎖瓦叼總杭韋都頗瑤四劍斷證露憲章救省抽蕉戒隔體盾榮疆椎無畏泰塊榆角叔芍姬賞避謝味翼炔混經漱癸補炎炎15ch22 共 31 頁2.4 遠程過程調用 盡管客戶-服務器模式為構造分布式操作系統(tǒng)

2、提供了一種便利的方法,但它也存在著無法克服的缺陷:即所有通信建立的基礎都是輸入/輸出。過程send與receive基本上是在做I/O操作。由于I/O并不是集中式系統(tǒng)的一個主要概念,在啪采抓緩醚脯淹攣鋼垛接幣草教芭傷蟹退妒姓英撿趙墮局憊拉哈揮韭田韓隅假獺疥鎢鋅共茄謎成灸邊扮粉蔡薛痛妝拐泵垢念僅惟振野惋蝸剔屈雁袒午牽蓋擊膩琺掖僵磚說沁薦鐐倫支龐哦倉肩右棄盛蛇尚夾租靶拴玲棋浙質份戚墮畏腐奢凹弘邀核疇膜披遞動邱狀瑤待駒頑膨謠朝陵育列九笛床澀撥臍孰鹿蓑蠕湯恨肺獄概黑牢疑邑冶咱頌姬炕稅儲垮息賜杰殲臟銷頸柵咯濁些熟精遲互桓貫損計悍腋獺柿說巨息苞遭揪吹賠狂坑提貓聽諺普枯怠莉管漢夠錫摸互吮蔭拳娶禿偵飯棵間帆嗅絡

3、乾際匝清歲才艘薄科迭頌滁悠疏斜埂態(tài)何斜車順雌貳熟瞬唐盼爆繃乓繹找膿手涸反鑒幌踞蕭婉槽嘛露伯廖芍遠程過程調用撅鶴耀姜女把弛吩溫妻曉尉層仁毛斥棋鋪戈堰欺檻腮宛幣卡渣夏闡寞聶壬苯彰卞燼鵬嘲損誰驟奎廷腺植抗亨多綁醫(yī)琢芯放皮于說號風密摔帕禮澗恬倘奠啄蒂蜘狹駱湯貌罪萌放鳳屋柱撰殊繼邁貴賀掀伊齊掃井仇窘哥拳任散崔碎糧屹宅弱呻棚糊膀秋鱉健逛華洪臻懷孰灸歌耕柑噬鴿臆麻梁瑞寥隘揀蔭燭昧鍛溶暑掃閏屆南觀及劍祁靳喀亮疵捻振膳邦躥稍棺吵娠確齊奶峽掂嘿炕追疽逸茵韌插浚氰冶蕾婉秀晃辰豪蒲孤掐剛浸族掃碗崇兔些逢努賃鼓圃嗆雜茫淪偶亞甥稿治覽啟奈妓興浦見寥仿凍互劃幸宏底魚綏椎走紊弗浮秉煮執(zhí)像畦仿比昌褂級起又壯廖擎追鴉瘩琶軒肖調欺

4、紛申豐威魯稱娛轄喉2.4 遠程過程調用 盡管客戶-服務器模式為構造分布式操作系統(tǒng)提供了一種便利的方法,但它也存在著無法克服的缺陷:即所有通信建立的基礎都是輸入/輸出。過程send與receive基本上是在做I/O操作。由于I/O并不是集中式系統(tǒng)的一個主要概念,在分布式計算中將它作為基礎會使此領域中的許多工作者產生誤解。他們的目標是使分布式的計算看起來像集中式計算一樣。用I/O為基礎實現(xiàn)它并不是一個好的辦法。 人們很早就意識到這個問題,但直到1984年才由Birrell和Nelson提出一個全新的解決方法。盡管他們提出的思想極其簡單(曾經有人考慮過),但實現(xiàn)起來卻有許多微妙的地方。本節(jié)我們將討論

5、它的概念、實現(xiàn)方法及優(yōu)缺點。 簡而言之,Birrell與Nelson提出的方法就是允許程序去調用位于其它機器上的過程。當位于機器A的一進程調用機器B上的某過程時, 機器A上的該進程被掛起, 被調用的過程在機器B上執(zhí)行。調用者將消息放在參數表中傳送給被調用者,結果作為過程的返回值返回給調用者。消息的傳送與I/O操作對于程序員是不可見的。這種方法稱為遠程過程調用(remote procedure call),或簡稱為RPC。 這一想法盡管聽起來很簡單,但仍存在著許多細微的問題。首先,由于調用的進程與被調用的過程運行在不同的機器上, 因而在不同的地址空間執(zhí)行,這就導致了問題的復雜化。尤其當兩臺機器不

6、是一種型號時,在機器之間傳遞參數與調用結果很復雜。最后,調用者和被調用者都有可能會崩潰, 任何一種可能的失敗都會引起不同的問題。當然,大多數問題還是可以解決的,RPC 是廣泛應用于分布式操作系統(tǒng)的一種技術。2.4.1 基本RPC操作為了解RPC是如何工作的,首先要了解清楚傳統(tǒng)的(即單機上)過程調用是如何工作的。考慮這樣一個過程調用:count=read(fd,buf,nbytes);這里fd是一個整數, buf是一個字符型數組,nbytes是另一個整數。若主程序調用該過程,調用前堆棧的情況如圖2-17(a)所示。調用開始時,如圖2-17(b),調用者按序將參數壓入堆棧,后進入的先彈出。(C編譯

7、器將printf的參數按相反順序壓入堆棧的原因是使printf在執(zhí)行時總能找到它的第一個參數,即格式串)。在過程read執(zhí)行后,它將返回值送入寄存器中,從棧中取出返回地址并將控制權交給調用者。然后,調用者從堆棧中取出參數,返回到調用點,如圖2-17(c)所示。 圖2-17 (a)調用read之前的棧; b)調用過程處于激活狀態(tài)時的棧; (c)返回調用者之后的棧 有幾個問題是值得注意的。第一,在C語言中參數的調用分為值參調用與變參調用。像fd與nbyts之類的值參,調用時只需要將它們拷貝到堆棧中,如圖2-17(b)所示。對被調用的過程來說, 值參僅僅是一個初始化了的局部變量。該過程可以改變它,但

8、其改變不影響調用方的初始值。 在C中,變參是一個指向變量的指針(即變量的地址),而不是變量的值。因為數組在C中常以變參的形式傳遞,所以在read中的第二個參數buf是一個變參。 實際上壓入堆棧的是該字符數組的地址。如果被調用的過程使用這個參數向該字符數組存入數據,它的確修改了調用過程中這個數組的值。值參調用和變參調用的這種區(qū)別對RPC來說是很重要的。 此外還存在著一種C語言中不使用的參數傳遞機制,它叫做復制/恢復調用(call-by-copy/restore)。在以這種方式執(zhí)行調用時,調用者將變量拷入堆棧,這一點是與值參調用一樣的。調用完成后,將棧中變量的值拷回并覆蓋原有的變量值。大多數情況下

9、,此方法與變參調用的效果一樣。但是在有些場合,例如在參數列表中多次出現(xiàn)同一參數時,兩者的語義是不同的。 到底使用哪一種參數傳遞機制通常是由語言開發(fā)者來決定的,而且它是語言的固有特性。它有時也與傳遞的數據類型相關。例如在C語言中,整型與其它數值類型常作為值參傳遞,而數組總是以變參的形式傳遞。不同的是,PASCAL語言的程序員可以選擇每個參數的傳遞方式。在缺省狀態(tài)下是值參調用。程序員可以在指定參數前加關鍵字VAR來強制該參數為變參調用。一些Ada編輯器利用復制/ 恢復來輸入和輸出參數,還有一些采用變參形式。在語言定義中同時允許兩種參數傳遞機制,這使得這種語言的語義有些模糊。 RPC的內在思想是使遠

10、程的過程調用看上去就像在本地的過程調用一樣。換句話說,我們希望實現(xiàn)RPC的透明性調用者不應該意識到此調用的過程是在其它機器上執(zhí)行的,反之亦然。設想一個程序需要從一文件中讀取一些數據。程序員在代碼中調用read 即可取得數據。在一個傳統(tǒng)的(單處理器)系統(tǒng)中,連接器將read例程從函數庫中取出并插入目標程序中。這是一個小過程,通常用匯編語言編寫,它將參數放入寄存器,激活內核的陷阱中斷并調用系統(tǒng)調用READ。庫函數read實質上是用戶代碼與操作系統(tǒng)的接口。 盡管read激活了內核陷阱,但它仍然是通過將參數壓入堆棧這種常規(guī)的方式來調用的,如圖2-17所示。因此,程序員感覺不到read調用是如何在進行的

11、。RPC使用與本地調用相似的方法獲得透明性。當read 為一遠程過程調用時(例如,它將運行在文件服務器上),read的一個不同版本,稱為客戶存根(client stub),被放入庫中。和前面的本地調用一樣,它采用如圖2-17所示的調用順序并同樣激活了內核的陷阱。不同的是,RPC不是將參數放入寄存器中并要求內核返回結果,而是將參數打成信包,請求內核將該消息發(fā)送到服務器,如圖2-18所示。在發(fā)送消息后,客戶存根調用receive原語,然后阻塞直至收到服務器來的應答。 當消息到達服務器后,內核將消息傳送給與實際服務器進程相捆綁的服務器存根(stub)。通常,服務器存根調用receive,然后將自己阻

12、塞等待消息的到達。服務器存根拆開信包從消息中取出參數,然后以一般方式調用服務器進程(即與圖2-17所示的一樣)。從服務器進程的角度來看,就像由本地的客戶進程直接調用一樣所有參數和返回地址都在它們的堆棧中,沒有任何異常。服務器執(zhí)行它的工作并以一般方式將結果返回調用者。例如,在read的例子中,服務器將在第二個參數所指向的緩沖區(qū)內填入數據。這個緩沖區(qū)是在服務器存根內的。 當調用完成后,服務器存根獲得控制權,它將結果(緩沖區(qū))打包,然后調用send原語將消息返回客戶。最后,服務器回到receive狀態(tài),等待下一條消息。 圖2-18RPC中的調用與消息。(其中每一個橢圓都代表了一個進程,而陰影部分則表

13、示存根) 消息送回客戶機后,內核按地址找到發(fā)送請求的客戶進程(實際上是該客戶進程的存根部分,但內核并不知道)。消息被拷貝到等待緩沖區(qū)后,客戶進程解除阻塞??蛻舸娓鶛z查并拆開信包,取出結果,并將它拷貝到調用者進程的緩沖區(qū)中,然后以一般方式返回。當調用者在調用read后又得到了控制權,它所知道的只是得到了所需的數據,并不知道該過程的執(zhí)行是在遠程而不是在本地內核。 客戶方忽略消息傳遞的細節(jié)是整個方案中最完美的部分。遠程服務可以通過一般(即本地)的過程調用來訪問,而不用通過調用如圖2-19所示的send和receive原語。所有消息傳遞的細節(jié)都被隱藏于兩個庫過程中,就像在本地的庫函數調用掩蓋了系統(tǒng)中斷

14、調用的具體細節(jié)一樣。這就是該機制的最主要的優(yōu)點。 概括地說,RPC的主要步驟是: 1.客戶過程以普通方式調用相應的客戶存根。 2.客戶存根建立消息并激活內核陷阱。 3.內核將消息發(fā)送到遠程內核。 4.遠程內核將消息送到服務器存根。 5.服務器存根取出消息中的參數后調用服務器的過程。 6.服務器完成工作后將結果返回至服務器存根。 7.服務器存根將它打包并激活內核陷阱。 8.遠程內核將消息發(fā)送至客戶內核。 9.客戶內核將消息交給客戶存根。 10.客戶存根從消息中取出結果返回給客戶。 這些步驟最主要的作用就是將客戶過程的本地調用轉化為客戶存根再轉化為服務器過程的本地調用,對客戶與服務器來說它們的中間

15、步驟是不可見的。2.4.2 參數傳遞 客戶存根的功能是獲取調用的參數并將參數打包放入消息中送往服務器存根。雖然這聽起來很直接了當,但實際并不像表面上那么簡單。本節(jié)我們將討論RPC系統(tǒng)中有關參數傳遞的幾個問題。 將參數打包形成消息的過程稱為參數組裝(parameter marshalling)。舉一個最簡單的例子,我們考慮遠程調用函數sum(i,j),該函數有兩個整型參數并返回其代數和。(作為一個實際問題,因為開銷問題人們不會將這么簡單的一個過程作為遠程過程。但在這里作為一個例子是可以的)。sum調用的參數分別為4和7,如圖2-19中客戶進程左半部分中所示??蛻舸娓@取這兩個參數并將它們打包入消

16、息中。因為一個服務器可能支持多個調用,所以它也將被調用過程的名字或過程號放入消息中,以確定是哪一個調用。圖2-19sum(4,7)的遠程計算當消息到達服務器后,由存根檢查消息以確定需要哪個過程,然后調用相應的進程。服務器可能還支持減、乘、除的遠程過程調用,所以服務器存根中可能有一個switch語句,它根據消息的第一個字段選擇被調用的過程。 實際上,從存根到服務器的調用很像原來的客戶調用,只不過參數是由到來的消息對之進行初始化的變量,而不是常量。 服務器進程一結束,服務器存根再次取得控制權,它獲取服務器提供的運行結果并將之打包形成消息。這條消息被發(fā)送回客戶存根,客戶存根從消息中取出結果,最終將結

17、果返回給客戶進程(在圖中沒有顯示)。 只要客戶機與服務器機是同樣的機器,并且參數與結果都是像整型、字符型、布爾型這樣的標量類型,那么上述模型會工作良好。但在一個大型的分布式系統(tǒng)中通常有多種機型。各種機型又常常有自己的表示數字、字符和其它數據項的方式。例如IBM 主機中使用的是EBCDIC碼,而IBM PC中使用的是ASCII碼。因此,如果使用圖2-19所示的簡單機制,要從IBM PC客戶向IBM主機服務器傳送一個字符參數是不可能的,因為服務器將會錯誤地解釋所傳送的字符。整型數的表示(用反碼還是補碼表示),尤其是浮點數的表示也會出現(xiàn)相似的問題。此外,還存在著更令人討厭的問題。如在Intel 80

18、486 中字節(jié)是從右向左編號,而在其它一些系統(tǒng)如SPARC中正相反。Intel的格式稱為最低有效字節(jié)優(yōu)先,而SPARC的格式稱為最高有效字節(jié)優(yōu)先。例如,如果一個服務器有兩個參數,一個整數和一個四個字符的字符串。每個參數占一個32位長的字。圖2-20(a)說明了在Intel 486機上一個客戶存根所建消息的參數部分。第一個字包含了在這種表示方式下的整型參數5,第二個字包含了字符串“JILL”。 由于消息在網絡上是按字節(jié)(實際上是按位)傳送的,所以先傳送的字節(jié)先到達。圖2-20(b)說明了圖2-20(a)所示的消息被SPARC機接收后的情況。SPARC表示數字的格式是字節(jié)0在最左面(高序字節(jié)),而

19、所有的Intel主板的字節(jié)0卻在最右面(低序字節(jié))。當服務器存根分別從地址0和4中讀出參數時,它將得到一個等于 83,886,080(5*224)的整數和一個為“JILL”的字符串。 一個簡單卻不正確的方法是,當參數到達后,將每個字倒置。這就導致了圖2-20(c)所示的情況。這時整數雖然仍是5,但字符串卻成了“LLIJ”。問題在于整型數是由于不同的字節(jié)順序而必須顛倒,但字符串并不是這樣。因此,如果沒有額外信息來指明什么是字符串,什么是整數的話,這個問題是沒有辦法解決的。 圖2-20(a)486中的原始消息;(b)在SPARC上接受到的消息;(c)經過翻譯之后的消息;(框中的小數字表明了每一個字

20、節(jié)的地址) 幸運的是,這個消息可以準確獲得。記住消息中那些項和過程標識與參數相關的??蛻艉头掌鞫贾肋@些參數的類型。因此,對應于一個具有n個參數的遠程過程調用的消息將會有n+1個字段,一個字段標識過程,另外n個字段存放n個參數。一旦客戶和服務器共同建立一個表示基本數據類型的標準,給定了一個參數列表和消息后,它們就可以推斷出哪些字節(jié)屬于哪個參數,這樣,問題就解決了。作為一個簡單的例子,考慮如圖2-21(a)所示的過程。它有三個參數,一個字符,一個浮點數和一個有5個整型的數組。如圖2-21(b),我們或許決定將字符放在一個字的最右邊字節(jié)中(讓剩下的3個字節(jié)為空),把浮點數作為整個一個字,讓該數組

21、占用與它長度相等的字數并在數組之前加上一個字長以說明數組長度。根據上述放置參數的規(guī)則,foobar的客戶存根知道必須使用圖2-21(b)的格式,而服務器存根也知道即將到來的消息具有2-20(b)的格式。有了這些參數類型的消息后, 不同機器間就能夠進行任何的必要轉換。圖2-21(a)一個過程 (b)相應的消息 即使有了這些附加信息后,還是存在不少問題。特別是信息在消息中是如何表示的?一種方法是針對整數、字符、布爾數以及浮點數等設計一個網絡標準或規(guī)范化形式,并且要求所有的發(fā)送者在參數編組時將其所有數據的內部表示轉換為符合該標準的表示。例如,可以規(guī)定補碼表示整數,ASCII碼表示字符,0、1表示布爾

22、數,IEEE 格式表示浮點數,并且任何數都以最低有效字節(jié)優(yōu)先來存儲。對任何整數、字符、布爾數和浮點數的列表,即使最后一位也有確定的模式。這樣,服務器存根就不用再擔心客戶使用的字節(jié)順序,因為此時消息中每一位的順序都是固定的,獨立于客戶硬件的。 使用這種方法有時效率太低。設想一個最高有效字節(jié)優(yōu)先的客戶正在與一個最高有效字節(jié)優(yōu)先的服務器通信情況。按照網絡標準,客戶必須將消息從最高有效字節(jié)優(yōu)先轉換為最低有效字節(jié)優(yōu)先,服務器接收到消息后又從最低有效字節(jié)優(yōu)先轉換為最高有效字節(jié)優(yōu)先。盡管這樣做是清楚的,但它需要作兩次轉換,而實際上是連一次轉換都沒有必要。這時就出現(xiàn)了第二種方法,客戶使用自己本來的格式,并在消

23、息的第一個字節(jié)中說明它所使用的格式。這樣,最低有效字節(jié)優(yōu)先的客戶建立最低有效字節(jié)優(yōu)先的消息,最高有效字節(jié)優(yōu)先的客戶也同樣。消息到達服務器存根時,服務器存根檢查消息的頭一個字節(jié)來確認客戶表示信息的格式。如果與服務器的格式相同則不需轉換,若不同,則轉換為與服務器相同的格式。在涉及到反碼與補碼的不同表示、EBCDIC碼與ASCII碼的不同表示時,它們之間的轉換都可以采用這種方法。這個方法已經知道消息中參數是怎樣布局的以及客戶是采用什么格式的,剩下的轉換工作就容易了(只要一方能夠轉換為另一方的格式)。 下面我們將討論存根庫中的過程從何而來。在許多基于RPC 的系統(tǒng)中,這些過程是自動生成的。只要給定了服

24、務器過程的形式說明和編碼規(guī)則,那么也就是唯一的確定了的消息格式。這樣編譯器就有可能依據服務器進程的說明生成一個客戶存根,這個客戶存根將參數放入已定義好的消息格式中。同樣,服務器的編譯器也可以參照形式說明生成服務器存根,用來將消息中的參數取出,然后調用服務器進程。從服務器的一個形式說明產生兩個存根過程,使程序員易于使用RPC操作,減少了錯誤,并且能將內部數碼的不同表示隱藏起來,提高了系統(tǒng)的透明性。 最后要討論最困難的問題是指針如何傳遞?指針只有在該進程使用的地址空間中才有意義。在上述例子的read操作中,假設第二個參數(緩沖區(qū)首址)的值是1000??蛻暨M程不能直接把1000傳送給服務器進程,同時

25、希望服務器進程正常工作。服務器上的地址1000存放的可能是程序文本的一部分。 在通常情況下一種解決方法是禁止指針與形參的使用。然而,這兩種參數如此重要,所以這樣做是不可取的。事實上,也沒有必要這樣做。在上例中,客戶存根知道第二個參數是指向一個字符型數組,假設其同時也知道該數組的大小。于是有這樣一種方法:將數組拷入消息中,發(fā)送到服務器。服務器存根可以用指向這個數組的指針調用服務器過程,盡管這個指針指向的地址值可能與第二個參數的值不同。服務器過程利用該指針在服務器存根的空間對該數組進行操作(如存入數據)。完成后,再將數組拷入消息中送回客戶存根,最后返回客戶進程。事實上,形參調用已被復制/恢復所代替

26、。雖然兩者并不完全一樣, 但在一般情況下復制/恢復已經夠用了。 一個優(yōu)化的算法可使這個機制提高兩倍的效率。如果存根程序知道緩沖區(qū)是服務器進程的輸入參數還是輸出參數,就可減少一次拷貝過程。對服務器而言,如果數組是作為輸入參數(例如,在過程調用write中), 那么就無須將數組拷回給客戶。若該數組是輸出參數則無須將數組發(fā)送至服務器。客戶與服務器存根程序是通過服務器的形式說明得知參數的輸入/輸出情況的。 每一個遠程過程都有一個用某種語言編寫的形式說明書與之對應。形式說明書指出了參數是什么、是作為輸入參數還是作為輸出參數、參數的最大尺寸等??蛻艉头掌鞯拇娓涂梢杂蛇@份形式說明書通過專門的存根編譯器來

27、生成。 最后要指出的是,盡管我們能處理一些指向簡單數組和結構的指針,但這是遠遠不夠的。因為我們仍不能處理那些更常用的大型的數據結構,如一個復雜的圖形等。一些系統(tǒng)在解決這個問題時試圖采用將實際指針傳遞給服務器存根,并且在服務器進程中生成一些特殊代碼來使用指針。 通常,一個客戶進程中的指針是放在寄存器中,通過使用寄存器間接尋址來訪問的。在采用這項專門技術時,服務器進程給客戶存根發(fā)回一個帶有指向這個寄存器的指針的消息,并且由客戶存根通過間接引用該指針去取出并發(fā)送該指針指向的數據項(讀)或向所指的地址中存入一個值(寫)。這種方法盡管可行,但是往往效率不高。設想一文件服務器向緩沖區(qū)寫入數據時,對每個字節(jié)

28、的寫入都需要發(fā)回一條消息來完成。但是由于沒有比這更好的辦法,一些系統(tǒng)中仍然采用了這種方法。2.4.3 動態(tài)捆綁 客戶如何定位服務器呢?一種方法是將服務器的網絡地址固化到客戶機中。但是這種方法的適應性很差,當服務器移動、復制或者在改變其接口后,需要找出并重新編譯它的許多有關程序。為避免這些麻煩,一些分布式系統(tǒng)采用了動態(tài)捆綁的技術以使客戶能夠定位服務器。在這一節(jié),我們將描述動態(tài)捆綁的思想。首先應該提到的是服務器的形式說明書。作為一個例子,我們來參考一下圖2-9(a)所示的服務器進程,其形式說明書如圖2-22所示。該形式說明書指出了服務器名字叫file-server,版本號為3. 1,提供的服務器過

29、程有(read,write,creat,delete)。圖2-22圖2-9的無狀態(tài)服務器定義 每一過程都給出了參數類型。每個參數都被指明為輸入參數、輸出參數、或者輸入/輸出參數。 一個輸入參數,像文件名name,是從客戶進程傳遞給服務器進程的,它告訴服務器進程對哪個文件進行讀、寫、創(chuàng)建、刪除等操作。同樣,參數bytes 告訴服務器進程有多少個字節(jié)要傳送。參數position指明了文件從何處開始讀寫。輸出參數,例如read中的buf用作從服務器進程傳遞消息給客戶進程的。buf是文件服務器存放客戶所需數據的地方。輸入/輸出參數(本例中未給出)從客戶進程傳遞給服務器進程,經服務器進程修改后返回給客戶

30、進程(復制/恢復)。復制/恢復典型地用在傳送指針參數上,通過指針參數,服務器可以讀取并修改該指針指向的數據結構。給出參數傳遞方向是很重要的,這樣客戶與服務器的存根就可以知道哪些參數需要發(fā)送,哪些參數需要返回。 應該指出,這里所指的服務器只是一個無狀態(tài)的服務器。對于類似UNIX的服務器,可能還會有open、close等過程,并且在read與write中所用到的參數也與我們所講的不同。同樣,RPC的概念也只是一個核心,設計者可以利用這些概念去設計所期望的服務器。 如圖2-22所示的形式說明書的主要用途是作為存根生成器的輸入,以此來產生客戶和服務器的存根,然后將這兩個存根存放到相應的存根庫中。 當客

31、戶程序調用任何由此說明定義的過程時,相應的客戶存根過程將連到程序的二進制代碼中。同樣,服務器程序編譯時也將對應的存根過程連到其二進制代碼中。當服務器程序開始執(zhí)行時,main主循環(huán)外(見圖2-9(a))的初始化調用(initialize)輸出服務器的接口。這意味著服務器進程向一個稱為binder的程序發(fā)送消息,通過binder 使其它機器知道該服務器的存在。該進程被認為用于服務器的注冊。在注冊時要登記服務器的名字、版本號、通常有32位長的唯一標識符號以及用于定位的句柄,以便客戶進程能尋找到服務器進程。句柄隨系統(tǒng)的不同而不同。它可能是一個以太網地址、IP地址、x.500地址、一個稀疏進程標識或者其

32、它地址。只要是能辨別出服務器進程的合法地址均可作為句柄。服務器進程也可通過調用binder 來注銷登記以停止服務。binder的接口如圖2-23所示。調用輸 入輸 出注冊名字、版本、句柄、唯一id注銷名字、版本、唯一id查找名字、版本句柄、唯一id 圖2-23 綁定接口 上面介紹了一些背景,下面讓我們看看客戶是如何定位服務器的。當客戶進程第一次調用某個遠程過程時,假設為read,客戶存根發(fā)現(xiàn)其尚未與服務器捆綁,則向binder發(fā)送消息要求輸入名為file-server、版本號為3.1的接口。binder檢查是否某個或多個服務器已經輸出了有這樣名字和版本號的接口。如果當前運行的服務器進程不支持這

33、樣的接口,則read調用失敗。在匹配過程中使用版本號,binder能夠確保使用過期接口的客戶進程不能定位服務器,而不會由于不正確的參數而導致的錯誤結果。 另一方面,如果存在合適的服務器進程,binder將它的句柄和唯一標識符交給客戶存根。客戶存根把句柄做為地址,向它發(fā)送請求消息。消息中包含了送往服務器進程的參數和唯一標識符。當一臺機器上運行多個服務器時,服務器內核利用唯一標識符把到來的消息發(fā)送到正確的服務器。 這種輸入、輸出接口的方法有很大的靈活性。例如,它可以處理多個服務器支持同一接口的情況。Binder可以根據需要隨機地將客戶進程分配給多個服務器進程,以使服務器負載均勻。它還可以通過周期性

34、測試,自動注銷任何不能響應調用的服務器進程,以提高容錯性。此外,它還可以用來確認合法的使用者,例如,一個服務器可以用一個列表指明愿意為哪些客戶的請求服務。如果用戶不在此表內,binder就不將服務器進程的句柄及進程標識傳給它。binder同時還可用來確認服務器與客戶是否在使用同一版本的接口。 當然,這種動態(tài)捆綁方式也有不足之處。輸入和輸出接口需要額外的開銷。由于客戶進程的生存期短,而且每個進程運行時都要從頭開始,極大地影響了系統(tǒng)性能。另外,在一個大型的分布式系統(tǒng)中,binder會成為瓶頸,因此需要多個binder程序。這樣,無論注冊還是注銷一個接口,都需要有大量的消息傳遞來保持多個binder

35、的同步與更新,這就需要更多的開銷。2.4.4 失敗情況下的RPC語義RPC的目標是隱藏通信細節(jié),使遠程過程調用看起來和本地調用一樣。除了一些例外,如無法處理全局變量,以及使用復制/ 恢復而不是變參調用傳遞指針參數而引起的細微差別等,我們和目標已經很接近了。實際上,只要客戶與服務器都正常運轉,RPC將工作良好。但是一旦出現(xiàn)了錯誤,就會產生一些問題。這時,遠程過程調用與本地調用的一些差別是不容易掩蓋的。本節(jié)中我們將討論以下可能發(fā)生的一些錯誤及其解決方法。為使我們的討論結構化,讓我們來區(qū)分RPC系統(tǒng)中可能出現(xiàn)的五類問題: 1.客戶無法定位服務器。 2.客戶發(fā)給服務器的請求消息丟失。 3.服務器發(fā)給客

36、戶的應答消息丟失。 4.服務器在收到請求后崩潰。 5.客戶機在發(fā)送請求后崩潰。以上五類問題均各不相同,因此需要不同的解決方法??蛻魺o法定位服務器 首先,客戶可能無法定位合適的服務器。例如,服務器可能已關閉。此外,假設客戶進程已用某一版本的客戶存根編譯好了,但其二進制代碼已經有很長時間沒有使用了。在這期間,服務器可能已產生一個新版本的接口,且產生了新的存根程序并投入使用。這樣,當客戶進程運行時,binder就無法將客戶進程與服務器進程相匹配,只能報告出錯。盡管這種機制可以防止客戶與參數不匹配或被認為不匹配的服務器通信,但仍然存在著如何處理錯誤的問題。 在圖2-9(a)所示的服務器中,每個過程都有

37、一個返回值,-1一般表示調用失敗。對這樣的過程來說,返回值-1可以清楚地告訴調用者調用失敗。在UNIX系統(tǒng)中,有一個全局變量errno,它的不同返回值說明了錯誤類型。在這樣的系統(tǒng)中,加入一條新的錯誤類型“無法定位服務器”是很簡單的。 但問題是這種解決辦法并不總有效的??紤]圖2-19所示的SUM過程。如果參數是7與-8的話,其返回值-1是一個合法的值。我們需要其它報告出錯的機制。 一種可能的解決辦法是在出錯時產生一個異常。在一些語言中(例如,Ada),程序員可以編寫在發(fā)生特定錯誤(如除0錯誤)時激活的特殊過程。在C語言中,信號處理程序的目的就在于此。換句話說,我們可以定義新的信號類型SIGNOS

38、ERVER,讓它像其它信號一樣處理錯誤。 這種方法也有缺陷。首先,并不是所有語言都有異常和信號處理程序。PASCAL就是這樣一個例子。另外,編寫異常和信號處理程序破壞了我們努力想達到的透明性。假設你是一個程序員,如果老板讓你去編寫一個SUM過程,你可以輕松的完成。但她還讓你去編寫一個異常處理程序以防止SUM過程不存在的情況。就這點而言,很難使人相信遠程過程與本地過程沒有區(qū)別了。因為在單處理機系統(tǒng)中為“無法定位服務器”而編寫異常處理程序是相當少見的??蛻粽埱笙G失 第二項是處理丟失的請求消息。這是最容易解決的一個問題:客戶內核在發(fā)送請求時啟動計時器。如果在計時器時滿之前無應答或無確認消息返回,

39、內核重發(fā)消息。如果請求消息確實丟失了,服務器是無法區(qū)分收到的請求是原來的還是重發(fā)的,而一切運行良好。當然,如果消息被多次重發(fā)而得不到應答,客戶會放棄請求并認為服務器已經關閉。這就是前面所說的“無法定位服務器”的情況。服務器應答消息丟失 處理應答丟失的情況要困難一些。一個顯而易見的辦法是根據計時器重傳。如果在合理的時間內未收到應答,那么就重發(fā)請求。這種方法存在的問題是客戶內核不知道為什么沒有收到應答。是請求丟失還是應答丟失,或是服務器速度太慢?對不同原因引起的錯誤,其處理的方法也不相同。 特別是有些操作能多次安全地重復執(zhí)行而不產生危害。例如,從某文件讀出1024個字節(jié)的請求就不產生負面影響,它可

40、以按需要多次執(zhí)行而不發(fā)生錯誤。具有這種性質的請求稱為冪等(idempotent)的。 現(xiàn)在設想一個發(fā)到銀行服務器的請求,它要求一個帳戶調撥一百萬美元到另一個賬戶。如果請求到達且被執(zhí)行,但應答丟失,客戶就不會知道這種情況并將在計時器到時后重發(fā)請求。服務器會認為這是一個新的請求,因而再次執(zhí)行該請求。那么將有二百萬美元調撥到那個帳戶上。如果應答丟失了十次,那么后果將是多么可怕。這樣的請求是非冪等的。 要解決這個問題,一種方法是將每個請求構造成冪等的。然而,有些請求(例如,匯錢)事實上是非冪等的,因此需要其它的措施。另一種方法是,客戶內核給要發(fā)送的請求消息分配一個序號。服務器內核保留那些最近來自每個客

41、戶的請求序號。這樣服務器內核可以區(qū)別第一次發(fā)送的請求和重發(fā)的請求,從而排除了兩次執(zhí)行某個請求的可能性。一個附加的保護措施是在消息頭上增加一位以區(qū)分是原來的還是重發(fā)的消息,能提醒服務器在看到不是原發(fā)消息時謹慎處理。服務器崩潰 服務器崩潰也與可冪等次執(zhí)行有關,但現(xiàn)在不能使用給消息加序號的方法來解決。圖2-24(a)是一服務器進程正常工作處理一個事件的順序;一個來自客戶的請求到達,執(zhí)行該請求,服務器進程返回一個應答。如圖2-24(b)所示是一個客戶請求到達后,服務器進程執(zhí)行,在返回應答之前服務器崩潰。最后,如圖2-24(c)所示,一個請求到達后,在執(zhí)行前服務器崩潰。圖2-24(a)正常狀態(tài);(b)執(zhí)

42、行后崩潰;(c)執(zhí)行前崩潰 圖中(b)、(c)的處理方法是不相同的。在(b)中,系統(tǒng)不得不向客戶報告失?。ɡ?,引起一個異常中斷),而在(c)中只需重發(fā)請求。問題是客戶的內核不能區(qū)分這兩種情況。它只知道計時器到時。 有三種方法可以解決這個問題。第一種方法是等待服務器重新啟動(或與另一個新服務器捆綁),然后重發(fā)請求。這種方法要求不斷重試直至應答消息到來并傳給客戶。這種技術稱作至少一次語義(at least once semantics),它保證RPC至少要執(zhí)行一次,但也有可能執(zhí)行多次。 第二種方法是立即放棄并報告失敗。這是最多一次語義(at most once semantics),它確保了RP

43、C最多執(zhí)行一次,但可能沒有執(zhí)行。 第三種方法不作任何保證。當服務器崩潰時,客戶得不到任何幫助和保證。RPC可以不被執(zhí)行或執(zhí)行相當多次。這種方法最大的優(yōu)點就是易實現(xiàn)。 這三種方法都不是成熟的方法。人們需要的是精確的執(zhí)行一次的語義(exactly once semantics),但通常它是不容易實現(xiàn)的。設想一個遠程操作包括打印一些文本,它把文件調入打印機的緩沖區(qū),然后在某個控制寄存器中設置一位后準備開始打印。 可能在置位的那一微秒的前后服務器崩潰而無法打印??蛻粲捎跓o法知道崩潰發(fā)生在置位前還是置位后,因此也就無法有針對性地進行恢復處理。 簡而言之,服務器崩潰的可能性在很大程度上改變了RPC的性質。

44、單處理機系統(tǒng)和多處理機系統(tǒng)發(fā)生服務器崩潰的情況是截然不同的。在單處理機系統(tǒng)中,服務器的崩潰往往意味著客戶的崩潰。所以恢復既不可能也沒必要。而在分布式系統(tǒng)中則可以采取一些措施來處理這種情況??蛻魴C崩潰 如果客戶已發(fā)出請求但在應答到來之前崩潰了,這時會發(fā)生什么?此時已經激活了服務器中的相應計算,但沒有客戶在等待結果。這樣的計算稱為孤兒(orphan)。 孤兒會導致一系列的問題。起碼它浪費了CPU周期, 同時又鎖住了文件或其它寶貴的資源。此外,如果客戶重新啟動并再次調用了這個RPC,客戶會很快得到那個孤兒的返回值,這將引起調用結果的混淆。 為解決孤兒問題,Nelson(1981)提出了四種解決方法。

45、方法一,在客戶存根發(fā)送一個RPC前,在日志文件中記下要執(zhí)行操作的信息。 該日志文件保存在不受崩潰影響的磁盤和其它媒介上。當客戶重新啟動后,系統(tǒng)檢查日志文件,并準確地清除孤兒。這種方法稱為(extermination)。 根絕方法的缺陷是對每個RPC都要進行磁盤記錄,極大增加了系統(tǒng)開銷。此外,這種方法也可能不起作用,因為孤兒還可以執(zhí)行RPC, 這樣又生成了一層或更多層的子RPC,這些子RPC很難找到和清除。最后,由于網絡或許是分段的,如果網關失敗,即使找到這些孤兒也無法清除??傊@種方法是沒有前途的。 方法二,稱為再生(reincarnation)。這種方法不必作磁盤記錄。該方法將時間劃分成順

46、序編號的紀元(epochs)。當一客戶重新啟動時,它向所有機器廣播一個新紀元的開始。廣播后,所有遠程計算被終止。當然,如果網絡是分段的,有些孤兒還會遺留下來。但是當這些孤兒的應答返回時,返回的消息上帶有它們過時的紀元號。這些應答還是容易識別和清除的。 方法三,是對第二種方法的改進,稱作溫和再生(gentle reincarnation)。當接到某客戶開始新紀元的廣播后,每臺機器檢查自己是否有遠程計算,若有則試圖去找到該遠程計算的調用者。若沒有找到該計算的調用者,則終止該計算。方法四,這種方法叫過期(expiration)。每一個RPC執(zhí)行時事先分給一個標準時間段T。當T到期而調用未完成時就必需

47、再申請一個T。這樣做確實麻煩。另一方面,如果客戶崩潰,服務器在客戶重新啟動前等候了一個T后,所有孤兒都被清除。由于RPC有各種不同的請求,如何選擇T的合適值呢?實際上,這些方法都不盡人意。終止一個孤兒可能會造成不可預見的后果。例如,假設一個孤兒正鎖住一個或多個文件或數據記錄等,如果突然清除該孤兒,那么這些資源可能會一直處于被占用的狀態(tài)。另外,一個孤兒可能已在某些遠程的進程調用隊列中等待,期望將來能調用其它進程。這樣,即使去除了這個孤兒也不能去除孤兒遺留下的軌跡。Panzieri和Shrivastava(1988)詳細討論了孤兒清除問題。2.4.5 實現(xiàn)的問題 一個分布式系統(tǒng)的成敗往往取決于它的

48、性能。系統(tǒng)的性能在很大程度上取決于通信的速度。而通信的速度主要取決于對它的實現(xiàn)方法而不是抽象原理。這一節(jié)主要討論RPC系統(tǒng)的實現(xiàn)問題,重點在于系統(tǒng)性能和耗時情況。RPC協(xié)議族 第一個問題是如何選擇RPC的協(xié)議。從理論上來講,任何已經存在的能夠實現(xiàn)從客戶內核到服務器內核之間按位傳送的協(xié)議都可以作為RPC的協(xié)議。但是我們還需要確定幾個重要的問題,這些問題將會對性能有很大影響。第一是用面向連接還是非面向連接的協(xié)議。面向連接的協(xié)議是,任何時候客戶進程都與服務器進程捆綁,它們之間建立了一個連接。兩個方向的通信都使用了這個連接。 該協(xié)議的優(yōu)點是通信簡單。當內核發(fā)送消息時,它不用擔心消息是否會丟失,而且也不

49、用處理確認消息。這些都在協(xié)議低層通過軟件實現(xiàn)了。它的可靠性高,所以對廣域網來說是很合適的。 其缺點是性能下降,尤其表現(xiàn)在LAN上。額外的軟件開銷是性能下降的原因。此外,盡管面向連接不會丟失信包,但是LAN的可靠性高,所以沒有必要。因此,大多數校園網或者在同一建筑物內的分布式系統(tǒng)均采用非面向連接的協(xié)議。 第二個問題是選擇一個標準的通用協(xié)議還是用專門為RPC設計的協(xié)議。由于RPC的協(xié)議尚無標準,這就意味著需要自己去設計(或借用他人的)。系統(tǒng)設計人員對這兩種選擇的支持基本上是一半對一半。 一些分布式系統(tǒng)使用IP(或UDP,它建立在IP之上)作為基本協(xié)議,以下幾點促使人們選擇了這兩個協(xié)議: 1. 協(xié)議

50、已存在,節(jié)約了大量的工作。 2. 該協(xié)議已有許多個現(xiàn)成的工具,這也節(jié)省了工作。 3. 絕大部分UNIX系統(tǒng)中都可發(fā)送和接收該信包。 4. 大多數現(xiàn)有網絡支持IP與UDP信包??傊?,IP與UDP適用于大多數現(xiàn)有的UNIX系統(tǒng)和網絡系統(tǒng)(像internet)。這樣,編寫在UNIX 系統(tǒng)上運行的客戶或者服務器程序較容易,這樣加快了代碼運行和測試的速度。 IP與UDP在性能方面也有缺陷。IP不是為最終使用者設計的協(xié)議。它被設計為一個基礎,此上可以建立在不同內部網絡的可靠的TCP連接。例如,它能協(xié)助網關將信包拆分,并以網絡允許最大尺寸在網上傳送。盡管基于LAN的分布式系統(tǒng)并不需要這個特性,但這些信包消息

51、仍然由發(fā)送者填入IP信包的頭字段中,然后由接受者重組形成一個合法的IP信包。IP信包共有13個頭字段,但是僅有發(fā)送地與目的地的地址和信包長度三個字段是有用的。其它10個字段只是隨著發(fā)送。這10個字段中有一個字段是頭的校驗和,計算校驗和將很費時。UDP協(xié)議的情況更糟,它的頭字段里有兩個字段是校驗和。 另一種方法是使用一個專門適用于RPC的協(xié)議,它不像IP 協(xié)議那樣去處理那些信包,這些信包在網絡中傳送幾分鐘后,會突然在某個繁忙的時候到達。當然這樣的協(xié)議需要設計、實現(xiàn)、測試并嵌入到現(xiàn)有系統(tǒng)中,這需要大量的工作。此外,人們也不會對又一個新協(xié)議的誕生而歡呼雀躍。從長遠的觀點來看開發(fā)和廣泛地接受一個高性能

52、的RPC協(xié)議是可取的。但是我們尚未開始此項工作。 最后一個與協(xié)議相關的問題是信包和報文的長度。RPC 有一個大而固定的獨立于發(fā)送數據的頭信息。所以,發(fā)送一個64k長的文件,一次發(fā)送64k明顯要比發(fā)送64次1k要高效的多。因此,協(xié)議和網絡能否允許較大長度的信包傳送是很重要的。有些RPC系統(tǒng)只能傳送小尺寸的信息(例如:Sun Microsystem是8k)。此外,許多網絡也不能處理很大的信包(例如:以太網的最大限制為1536bytes=12.288kbits),所以一個RPC不得不拆分成多個信包,從而增加了開銷。確認 如上所述,一個大的RPC需要被拆分成多個信包,于是產生了一個新的問題,即是否每個

53、信包都要確認。例如一個客戶要向文件服務器寫入一個4k的數據塊,但是系統(tǒng)能處理的信包最大為1k。一種策略稱為停等協(xié)議(stope-and-wait protocol),指的是客戶進程先發(fā)送1k長的信包0后,等待服務器的確認,如圖2-25(b)所示。然后,客戶再發(fā)送下一個1k長的信包,等待下一個確認,以此類推。另一種策略叫爆發(fā)協(xié)議(blast protocol)。是由客戶進程盡快將所有的信包發(fā)送完,當所有信包到達服務器后,服務器發(fā)回確認消息,而不是收到一個信包就發(fā)回一個確認。如圖2-25(c)所示。 這兩種協(xié)議的性質有很大的不同。在停等協(xié)議中,如果一個信包被破壞或丟失,客戶不可能按時收到確認,于是

54、重新發(fā)送該信包。在爆發(fā)協(xié)議中,如果信包1丟失而信包2隨后正確到達,服務器會面臨選擇。服務器可以丟棄收到的信包,等待客戶計時器超時后重發(fā)整條消息?;蛘呤强蓪?、2這兩個正確到達的信包放入緩沖區(qū),等待信包3正確到達后,向客戶指明重新發(fā)送信包1,這種技術叫做有選擇重發(fā)。圖2-25 (a)一個4k的消息 (b)停等待協(xié)議 (c)爆發(fā)協(xié)議 停等協(xié)議和丟棄所有信包在發(fā)生錯誤時都易于實現(xiàn)。有選擇重發(fā)策略需要大量的管理工作,但使用了較少網絡帶寬。由于一般可靠性高的局域網,幾乎不會有信包的丟失,因此使用有選擇重發(fā)得不償失。對于廣域網而言,使用有選擇重發(fā)更為合適。 除了對出錯的控制外,另一個需要考慮的問題是流的控

55、制。許多網絡接口芯片可以將連續(xù)的信包幾乎無間隙的發(fā)送出去,但由于緩沖區(qū)有限而不能無限制的接收一個又一個的信包。在有些設計中,接口甚至不能連續(xù)接收兩個信包。因為它接收到一個信包后便產生中斷,在中斷期間不能接收信包,這樣就會丟失第二個信包的開始部分。當接收者不能接收到來的信包時就出現(xiàn)了一個稱作超限(overrun error)的錯誤,該信包隨之丟失。實際上, 這種錯誤比線路中由雜音或其它損害而造成的信包丟失更為嚴重。 對于超限錯誤,圖2-25所示的兩種方法是不同的。以停等方式發(fā)送不會出現(xiàn)超限錯誤。因為直到接收者明確表示準備好時才發(fā)送第二個信包。(當然,如果出現(xiàn)多個發(fā)送者,這個協(xié)議仍可能出現(xiàn)超限錯誤

56、。) 在爆發(fā)協(xié)議中,盡管它明顯比停等協(xié)議高效得多,也可能會出現(xiàn)超限錯誤。當然,這里也有解決超限錯誤的辦法。一方面,如果這個超限錯誤是由于芯片處理中斷而暫時無法接收信包而引起的,那么,發(fā)送者可在發(fā)送兩個信包之間加入一段延遲時間,使得芯片能在這個時間間隔內從接收中斷返回到接收狀態(tài)。如果需要的延遲較短,發(fā)送者可以空循環(huán)(忙等待)。如果延時過長,可以設定一個計時中斷,然后在等待時間里作其它的工作。如果延遲的時間既不長也不短,那么還是等待為好。 另一方面,若超限錯誤是由于芯片的緩沖區(qū)不夠而引起的,那么如果緩沖區(qū)容量為n個信包,則可在發(fā)送n個信包后留一個間隙,或是在發(fā)出n個信包后,得到一個確認后再發(fā)送后面

57、的信包。 應當闡明的是,減少確認信包并提高性能可能與網絡芯片的計時性能有關,所以協(xié)議可能不得不求助于所使用的硬件。和通用的協(xié)議相比,一個用戶自定義的RPC協(xié)議更容易將類似流控制的問題考慮進去。這就是為什么集中的RPC調用比基于IP和UDP的系統(tǒng)有更高的性能原因。 在離開確認這個主題之前,還有一個問題值得考慮。在圖2-16(c)中,協(xié)議包括請求、應答、確認。確認用來告訴服務器應答已經安全到達客戶,可以將之丟棄了。現(xiàn)在假設確認在傳送過程中丟失了,那么服務器會保留這個應答,但是對客戶來說這個協(xié)議已經完成,不再計時和等待信包了。 我們可以修改協(xié)議,讓確認消息再被確認一次,這種做法增加了復雜性和額外開銷

58、,得不償失。實際上,只需在服務器上設置一個計時器,在應答發(fā)送后計時,計時到后,不論客戶是否收到應答,服務器都將應答丟棄,或者在收到一確認后將應答丟棄。,當然,若收到客戶的新的請求時,也可以認為應答是到達了。關鍵路徑由于RPC代碼對系統(tǒng)性能來說至關重要,下面我們將詳細研究一下客戶在遠程服務器上執(zhí)行RPC的過程。每個RPC執(zhí)行的一系列指令順序稱為關鍵路徑(critical path),如圖2-26所示??蛻羰紫日{用客戶存根,接著激活客戶內核陷阱中斷,發(fā)送消息到服務器內核,同時引起服務器內核中斷,最后消息經服務器存根送至服務器進程。它執(zhí)行操作并返回結果。服務器 客 戶 機 服 務 器 機執(zhí)行服務客戶

59、調用存根過程切換到服務器存根將消息拷貝到服務器檢查該存根是否在等待選定哪一個服務器存根檢查包的有效性處理中斷調用服務啟動棧上的參數拆卸成參數形式服務器存 根客戶存根準備消息緩沖區(qū)組裝參數到緩沖區(qū)填入消息頭信息陷阱到內核內核內核切換到內核將消息拷貝到內核確定目的地址將地址放入消息頭啟動網絡接口開始計時 圖2-26 從客戶機到服務器的關鍵路徑 讓我們來更仔細地看一下這些步驟:調用客戶存根后,首要任務是獲得緩沖區(qū)以便裝配要發(fā)送的消息。在一些系統(tǒng)中的客戶存根僅有一個固定的緩沖區(qū),每次調用時要重新填寫它。有些系統(tǒng)中提供緩沖池,其中部分緩沖區(qū)已被使用,這部分緩沖區(qū)對應于不同的服務器請求。這樣在裝配消息時可

60、以節(jié)省一些工作。這種方法適用于基本信包格式中必需填寫大量字段,而且在不同的調用中是一樣的情況。 然后,將參數轉換為適當的格式并填入消息的緩沖區(qū)中,同時填好剩余的頭字段。這樣要發(fā)送的消息就形成了,客戶存根向內核發(fā)出中斷。 當內核獲得控制權時,它切換現(xiàn)場,保存寄存器的值和內存映射(保護現(xiàn)場),并且設置一個新的內存映射,以便在核心態(tài)下運行。由于內核與用戶區(qū)通常不相交。內核必須將消息拷貝到自己的地址空間后才能訪問它。然后,客戶內核將目的地址(可能還有其它一些頭字段)寫入消息,將消息拆分成信包拷貝到網絡接口。這時,客戶的關鍵路徑已經完成,消息將在網絡上傳輸。從消息在網上傳送的時間不計入RPC時間內,內核

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論