




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第15章高級(jí)進(jìn)程間通信15.1引言上一章說(shuō)明了各種UNIX系統(tǒng)提供的IPC經(jīng)典方法,包括:管道、FIFO、消息隊(duì)列、信號(hào)量和共享。本章介紹某些高級(jí)的IPC以及它們的應(yīng)用方法,包括:流管道和命名流管道。使用這些機(jī)制,可以在進(jìn)程間傳送打開(kāi)文件描述符。在分別為每一個(gè)客戶進(jìn)程提供一個(gè)通道的系統(tǒng)中,這些通信機(jī)制使客戶進(jìn)程能與精靈服務(wù)進(jìn)程會(huì)合。 4.2BSD和SVR3.2最早提供這些高級(jí)形式的IPC,但是至今尚未廣泛使用,也缺少參考文獻(xiàn)。本章中很多來(lái)自 Pressotto和Ritchie1990的。15.2流管道流管道是一個(gè)雙向(全雙工)管道。單個(gè)流管道就能向父、子進(jìn)程提供雙向的數(shù)據(jù)流。圖 15-1顯示了
2、觀察流管道的兩種方式。它與圖 14-1的唯一區(qū)別是雙向箭頭連線,因?yàn)榱鞴艿朗侨p工的。圖15-1 觀察流管道的兩種方式實(shí)例下面用一個(gè)流管道再次實(shí)現(xiàn)了程序 14-9的協(xié)作進(jìn)程實(shí)例。程序15-1是新的main函數(shù)。add2協(xié)作進(jìn)程與程序14-8中的相同。程序15-1調(diào)用了創(chuàng)建一個(gè)流管道的新函數(shù)s_pipe。(下面將說(shuō)明該函數(shù)的SVR4和4.3+BSD版本。)程序15-1 用流管道驅(qū)動(dòng)add2過(guò)濾進(jìn)程的程序用戶進(jìn)程用戶進(jìn)程或流管通內(nèi)核356UNIX環(huán)境高級(jí)編程父程序只使用fd0,子程序只使用fd1 。因?yàn)榱鞴艿赖拿恳欢硕际侨p工的,所以父進(jìn)程讀、寫fd0,而子程序?qū)d1到標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出。圖15
3、-2顯示了由此的描述符。第 15章 高級(jí)進(jìn)程間通信357s_pipe函數(shù)定義為與標(biāo)準(zhǔn)pipe函數(shù)類似。它的調(diào)用參數(shù)與pipe相同,但返回的描述符以讀 -寫方式打開(kāi)。實(shí)例 SVR4下的s_pipe函數(shù)程序15-2是s_pipe函數(shù)的SVR4版本。它只是調(diào)用創(chuàng)建全雙工管道的標(biāo)準(zhǔn)pipe函數(shù)。程序15-2 s_pipe函數(shù)的SVR4版本圖15-3顯示了SVR4之下管道的基本結(jié)構(gòu)。它主要是兩個(gè)相互連接的流首。因?yàn)楣艿朗且环N流設(shè)備,故可將處理模塊壓入管道的任一一端。15.5.1節(jié)將用此技術(shù)提供一個(gè)可以裝配名管道。實(shí)例 4.3+BSD之下的s_pipe函數(shù)程序15-3是s_pipe函數(shù)的BSD版本。此函數(shù)
4、在 4.2BSD及以后的各版本中起作用。它創(chuàng)建一對(duì)互連的UNIX域流套接口。程序15-3 s_pipe函數(shù)的BSD版本自4.2BSD開(kāi)始,常規(guī)的管道已用此方式實(shí)現(xiàn)。但是,當(dāng)調(diào)用 pipe時(shí),第一個(gè)描述符的寫端和第二個(gè)描述符的讀端都被關(guān)閉。為獲得全雙工管道,必須直接調(diào)用socketpair。用戶進(jìn)程流首流首內(nèi)核圖15-3 SVR4之下的管道在系統(tǒng)V的早期版本中也可以創(chuàng)建流管道,但要進(jìn)行的處理較多。有關(guān)在 SVR3.2下創(chuàng)建流管道的詳細(xì)情況,請(qǐng)參閱Stevens1990。父進(jìn)程子進(jìn)程(協(xié)作進(jìn)程)圖15-2 為協(xié)作進(jìn)程安排的描述符358UNIX環(huán)境高級(jí)編程15.3傳送文件描述符在進(jìn)程間傳送打開(kāi)文件描
5、述符的能力非常有用。用此可以對(duì)客戶機(jī) /服務(wù)器應(yīng)用進(jìn)行不同的設(shè)計(jì)。它允許一個(gè)進(jìn)程(一般是服務(wù)器)處理與打開(kāi)一個(gè)文件有關(guān)的所有操作(涉及的細(xì)節(jié)可能是:將網(wǎng)絡(luò)名翻譯為網(wǎng)絡(luò)地址、撥號(hào)調(diào)制解調(diào)器、協(xié)商文件鎖等。)以及向調(diào)用進(jìn)程返回一描述符,該描述符可被用于以后的所有 I/O函數(shù)。打開(kāi)文件或設(shè)備的所有細(xì)節(jié)對(duì)客戶而言都是透明的。下面進(jìn)一步說(shuō)明“從一個(gè)進(jìn)程向另一個(gè)進(jìn)程傳送一打開(kāi)文件描述符”的含義?;貞泩D 3-2,其中顯示了兩個(gè)進(jìn)程,它們打開(kāi)了同一文件。雖然它們共享同一 v節(jié)點(diǎn)表,但每個(gè)進(jìn)程都有它自己的文件表項(xiàng)。當(dāng)從一個(gè)進(jìn)程向另一個(gè)進(jìn)程傳送一打開(kāi)文件描述符時(shí),想要發(fā)送進(jìn)程和接收進(jìn)程共享同一文件表項(xiàng)。圖15-4
6、顯示了所希望的安排。在技術(shù)上,發(fā)送進(jìn)程實(shí)際上向接受進(jìn)程傳送一個(gè)指向一打開(kāi)文件表項(xiàng)的指針。該指針被分配存放在接收進(jìn)程的第一個(gè)可用描述符項(xiàng)中。(注意,不要得到錯(cuò)覺(jué)以為發(fā)送進(jìn)程和接收進(jìn)程中的描述符是相同的,通常它們是不同的。)這種情況與在fork之后,父、子進(jìn)程完全共個(gè)打開(kāi)文件表項(xiàng)相同(見(jiàn)圖 8-1)。當(dāng)發(fā)送進(jìn)程將描述符傳送給接收進(jìn)程后,通常它關(guān)閉該描述符。發(fā)送進(jìn)程關(guān)閉該描述符并不造成關(guān)閉該文件或設(shè)備,其原因是該描述符對(duì)應(yīng)的文件仍需為接收進(jìn)程打開(kāi)(即使接收進(jìn)程尚未接收到該描述符)。圖15-4 從上一進(jìn)程傳送一個(gè)打開(kāi)文件至下一進(jìn)程進(jìn)程表項(xiàng)fd標(biāo)志 ptr文件表 文件狀態(tài)標(biāo)志當(dāng)前文件位移v節(jié)點(diǎn)表v節(jié)點(diǎn)指
7、針v節(jié)點(diǎn)信息進(jìn)程表項(xiàng)i節(jié)點(diǎn)信息fd標(biāo)志 ptr當(dāng)前文件長(zhǎng)度4.2BSD支持傳送打開(kāi)描述符,但其實(shí)施中有些錯(cuò)誤。4.3BSD排除了這些錯(cuò)誤。 SVR3.2及以上版本都支持傳送打開(kāi)描述符。第 15章 高級(jí)進(jìn)程間通信359下面定義本章使用的三個(gè)函數(shù)(第18章也將使用)以發(fā)送和接收文件描述符。本節(jié)將會(huì)給出對(duì)于SVR4和4.3+BSD的這三個(gè)函數(shù)的不同實(shí)現(xiàn)。#include ourhdr.h send_fd(pipefd,send_err(pipefd,filedes);s us, const char e*rrmsg);兩個(gè)函數(shù)返回:若成功則為0,若出錯(cuò)則為-1recv_fd(pipefd, ssiz
8、e_t (u*serfunc)( , const void *, size_t); 返回:若成功則為文件描述符,若出錯(cuò)則 0當(dāng)一個(gè)進(jìn)程(通常是服務(wù)器)希望將一個(gè)描述符傳送給另一個(gè)進(jìn)程時(shí),它調(diào)用 send_fd或 send_err。等待接收描述符的進(jìn)程(客戶機(jī))調(diào)用recv_fd。send_fd經(jīng)由流管道spipefd發(fā)送描述符filedes。send_err 經(jīng)由流管道spipefd發(fā)送errmsg和 sus字節(jié)。sus的值應(yīng)在1255之間客戶機(jī)調(diào)用recv_fd接收一描述符。如果一切正常(發(fā)送者調(diào)用了send_fd),則作為函數(shù)值返回非負(fù)描述符。否則,返回值是由 send_err發(fā)送的sus
9、(1255之間的一個(gè)值)。另外,如果服務(wù)器發(fā)送了一條出錯(cuò)消息,則客戶機(jī)調(diào)用它自己的 userfunc處理該消息。userfunc的第一個(gè)參數(shù)是常數(shù)STDERR_FILENO,然后是指向出錯(cuò)消息的指針及其長(zhǎng)度。客戶機(jī)指定為UNIX的write函數(shù)。userfunc自己制定的協(xié)議。為發(fā)送一描述符, send_fd先發(fā)送兩實(shí)現(xiàn)了用于這三個(gè)函數(shù)的個(gè)0字節(jié),然后是實(shí)際描述符。為了發(fā)送一條出錯(cuò)消息, send_err 發(fā)送errmsg,然后是1個(gè)0字節(jié),最后是s us字節(jié)的絕對(duì)值(1255)。recv_fd讀流管道中所有字節(jié)直至null字符。null字符之前的所有字符都送給調(diào)用者的 userfunc。re
10、cv_fd讀到的下一個(gè)字節(jié)是s us字節(jié)。若s us字節(jié)為0,那么一個(gè)描述符已傳送,否則表示沒(méi)有接收到描述符send_err函數(shù)在將出錯(cuò)消息寫到流管道后,即調(diào)用send_fd函數(shù)。這示于程序15-4中。程序15-4 send_err函數(shù)360UNIX環(huán)境高級(jí)編程以下三節(jié)介紹了在SVR4、4.3BSD和4.3+BSD下,兩個(gè)函數(shù)send_fd和recv_fd的實(shí)際實(shí)現(xiàn)。15.3.1 SVR4在SVR4之下,文件描述符用兩個(gè)ioctl命令在一流管道換,這兩個(gè)命令是: I_SENDFD和I_RECVFD。為了發(fā)送一描述符,將ioctl的第三個(gè)參數(shù)設(shè)置為實(shí)際描述符。這示于程序15-5中。程序15-5S
11、VR4的send_fd函數(shù)當(dāng)接收一描述符時(shí),ioctl的第三個(gè)參數(shù)是一指向strrecvfd結(jié)構(gòu)的指針。recv_fd讀流管道直到接收到雙字節(jié)協(xié)議的第一個(gè)字節(jié)( null字節(jié))當(dāng)發(fā)出帶I_RECVFD命令的ioctl時(shí),在流讀首處的第一條消息應(yīng)當(dāng)是一個(gè)描述符,它是由 I_SENDFD發(fā)來(lái)的,或者得到一條出錯(cuò)消息。這示于程序15-6中。程序15-6 SVR4的recv_fd函數(shù)高級(jí)進(jìn)程間通信361第 15章15.3.2 4.3BSD不幸的是,對(duì)于4.3BSD以及在其基礎(chǔ)上構(gòu)造的SunOS和Ultrix,以及從4.3BSD Reno開(kāi)始的后續(xù)版本必須提供不同的實(shí)現(xiàn)。為了交換文件描述符,調(diào)用send
12、msg(2)和recvmsg(2)函數(shù)。這兩個(gè)函數(shù)的參數(shù)中都有一個(gè)指向m s g h d r的指針,該結(jié)構(gòu)包含了所有關(guān)于要發(fā)送和接收消息的信息。該結(jié)構(gòu)定義在 頭文件中,在BSD4.3之下,其樣式是:362UNIX環(huán)境高級(jí)編程頭兩個(gè)元素通常用于在網(wǎng)絡(luò)連接上發(fā)送數(shù)據(jù)報(bào)文,在這里,目的地址可以由每個(gè)數(shù)據(jù)報(bào)文指定。下面兩個(gè)元素使可以指定緩存的數(shù)組(散布讀和寫),這如同對(duì)readv和writev函數(shù)(見(jiàn)12.7節(jié))的說(shuō)明一樣。最后兩個(gè)元素處理存取權(quán)的傳送和接收。當(dāng)前唯一定義的存取權(quán)是文件描述符。存取權(quán)僅可一個(gè)UNIX域套接口傳送(即在4.3BSD之為流管道所使用的)。為了發(fā)送或接收一文件描述符,將msg
13、_accrights設(shè)置為指向該整型描述符,將msg_accrightslen設(shè)置為描述符的長(zhǎng)度(即整型的長(zhǎng)度)。僅當(dāng)此長(zhǎng)度非0時(shí),才傳送或接收描述符。程序15-7是4.3BSD的send_fd函數(shù)。程序15-7 4.3BDS的send_fd函數(shù)第 15章 高級(jí)進(jìn)程間通信363在sendmsg調(diào)用中,發(fā)送雙字節(jié)協(xié)議數(shù)據(jù)( null和sus字節(jié))和描述符。為了接收一文件描述符,從流管道讀,直至讀到 null字節(jié),它位于最后的sus字節(jié)之前。 null字節(jié)之前是一條出錯(cuò)消息,它來(lái)自發(fā)送者。這示于程序15-8。程序15-8 4.3BSD的recv_fd函數(shù)364UNIX環(huán)境高級(jí)編程注意,該程序總是準(zhǔn)
14、備接收一描述符(在每次調(diào)用 recvmsg之前,設(shè)置msg_accrights和 msg_accrightslen),但是僅當(dāng)在返回時(shí)msg_accrightslen非0,才確實(shí)接收到一描述符。15.3.3 4.3+BSD從4.3BSD Reno開(kāi)始,更改了msghdr結(jié)構(gòu)的定義。在以前版本中被稱之為“存取權(quán)”的最后兩個(gè)元素改稱為“輔助數(shù)據(jù)”。另外,在該結(jié)構(gòu)結(jié)束處增加了一個(gè)新成員msg_flags?,F(xiàn)在,msg_control字段指向一個(gè)cmsghdr(控制消息頭)結(jié)構(gòu)。為了發(fā)送一文件描述符,將cmsg_len設(shè)置為cmsghdr結(jié)構(gòu)長(zhǎng)度加一個(gè)整型(描述符)的長(zhǎng)度。將cmsg_level設(shè)置為
15、SOL_SOCKET,cmsg_type設(shè)置為SCM_RIGHTS,這表明正在傳送的是存取權(quán)( SCM表示套接口級(jí)控制消息)。實(shí)際描述符的存放位置緊隨在 cmsy_type字段之后,使用CMSG_DATA宏以獲得指向該整型數(shù)的指針。程序15-9示出了4.3BSD Reno之下的send_fd函數(shù)。程序15-9 4.3BSD的send_fd函數(shù)第 15章 高級(jí)進(jìn)程間通信365為了接收一描述符(見(jiàn)程序15-10),為cmsghdr結(jié)構(gòu)和一描述符分配了足夠的區(qū),設(shè)置msg_control使其指向所分配到的區(qū),然后調(diào)用recvmsg。程序15-10 4.3BSD Reno的recv_fd函數(shù)366UN
16、IX環(huán)境高級(jí)編程15.4open服務(wù)器第1版目前,使用文件描述符傳送技術(shù)開(kāi)發(fā)了一個(gè)open服務(wù)器:它是一個(gè)可執(zhí)行程序,由一個(gè)進(jìn)程執(zhí)行以打開(kāi)一個(gè)或多個(gè)文件。該服務(wù)器不是將文件送回調(diào)用進(jìn)程,而是送回一個(gè)打開(kāi)文件描述符。這使該服務(wù)器對(duì)任何類型的文件(例如調(diào)制解調(diào)器線或網(wǎng)絡(luò)連接)而不單是普通文件都能起作用。這也意味著,用 IPC交換最小量的信息 從客戶機(jī)到服務(wù)器傳送文件名和打開(kāi)方式,而從服務(wù)器到客戶機(jī)返回描述符。文件內(nèi)容則不需用IPC傳送。將服務(wù)器設(shè)計(jì)成一個(gè)單獨(dú)的可執(zhí)行程序有很多優(yōu)點(diǎn):任一客戶機(jī)都易于和服務(wù)器聯(lián)系,這類似于客戶機(jī)調(diào)用一庫(kù)函數(shù)。不需要將一特定服務(wù)編碼在應(yīng)用程序中,而是設(shè)計(jì)一種可供重用的設(shè)
17、施。如若需要更改服務(wù)器,那么也只影響一個(gè)程序。相反,更新一庫(kù)函數(shù)可能要更改調(diào)用此庫(kù)函數(shù)的所有程序(用連編程序重新連接)。共享庫(kù)函數(shù)可以簡(jiǎn)化這種更新。(3) 服務(wù)器可以是設(shè)置-用戶-ID程序,于是使其具有客戶機(jī)沒(méi)有的附加權(quán)。注意,一第 15章 高級(jí)進(jìn)程間通信367個(gè)庫(kù)函數(shù)(或共享庫(kù)函數(shù))不能提供這種能力??蛻魴C(jī)創(chuàng)建一流管道,然后調(diào)用 fork和exec以調(diào)用服務(wù)器??蛻魴C(jī)經(jīng)流管道發(fā)送請(qǐng)求,服務(wù)器經(jīng)管道回送響應(yīng)。定義客戶機(jī)和服務(wù)器間的協(xié)議如下:客戶機(jī)經(jīng)流管道向服務(wù)器發(fā)送下列形式的請(qǐng)求:open 0是open函數(shù)的第二個(gè)參數(shù),以十進(jìn)制表示。該請(qǐng)求字符串以null字節(jié)結(jié)尾。服務(wù)器調(diào)用send_fd 或
18、send_err回送一打開(kāi)描述符或一條出錯(cuò)消息。這是一個(gè)進(jìn)程向其父進(jìn)程發(fā)送一打開(kāi)描述符的實(shí)例。 15.6節(jié)將修改此實(shí)例,其中使用了一個(gè)精靈服務(wù)器,它將一個(gè)描述符發(fā)送給完全無(wú)關(guān)的進(jìn)程。程序15-11是頭文件open.h,它包括標(biāo)準(zhǔn)系統(tǒng)頭文件,并且定義了各個(gè)函數(shù)原型。程序15-11 open.h頭文件程序15-12是main函數(shù),其中包含一個(gè)循環(huán),它先從標(biāo)準(zhǔn)輸入讀一個(gè)路徑名,然后將該文至標(biāo)準(zhǔn)輸出。它調(diào)用函數(shù)csopen以與open服務(wù)器聯(lián)系,從其返回一打開(kāi)描述符。件程序15-12 main函數(shù)368UNIX環(huán)境高級(jí)編程程序15-13是函數(shù)csopen,它先創(chuàng)建一流管道,然后進(jìn)行服務(wù)器的fork和e
19、xec操作。程序15-13csopen函數(shù)子進(jìn)程關(guān)閉管道的一端,父進(jìn)程關(guān)閉另一端。子進(jìn)程也為它所執(zhí)行的服務(wù)器將管道的一端到其標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出 0(另一種可選擇的方案是將描述符fd1的ASCII 表示形式作為一個(gè)參數(shù)傳送給服務(wù)器。)父進(jìn)程將請(qǐng)求發(fā)送給服務(wù)器,請(qǐng)求中包含路徑名和打開(kāi)方式。最后,父進(jìn)程調(diào)用 recv_fd以返回描述符或錯(cuò)誤消息。如果服務(wù)器返回一錯(cuò)誤消息則調(diào)用write,向標(biāo)準(zhǔn)出錯(cuò)輸出該消息?,F(xiàn)在,觀察 open服務(wù)器。其程序是 opend,它由子進(jìn)程執(zhí)行(見(jiàn)程序 15 - 13 )。先觀察第 15章 高級(jí)進(jìn)程間通信369opend.h頭文件(見(jiàn)程序15-14),它包括了系統(tǒng)頭文件,
20、并且說(shuō)明了全局變量和函數(shù)原型。程序15-14 opend.h頭文件main函數(shù)(見(jiàn)程序15-15)經(jīng)流管道(它的標(biāo)準(zhǔn)輸入)讀來(lái)自客戶機(jī)的請(qǐng)求,然后調(diào)用函數(shù)request。程序15-15 main函數(shù)程序15-16中的request 函數(shù)承擔(dān)全部工作。它調(diào)用函數(shù) buf_args將客戶機(jī)請(qǐng)求分解成標(biāo)準(zhǔn) argv型的參數(shù)表,然后調(diào)用函數(shù)cli_args處理客戶機(jī)的參數(shù)。如果一切正常,則調(diào)用open打開(kāi)相應(yīng)文件,接著調(diào)用send_fd,經(jīng)由流管道(它的標(biāo)準(zhǔn)輸出)將描述符回送給客戶機(jī)。如果出錯(cuò)則調(diào)用send_err回送一則出錯(cuò)消息,其中使用了前面說(shuō)明的客戶機(jī)-服務(wù)器協(xié)議??蛻魴C(jī)請(qǐng)求是一個(gè)空的中斷的字符
21、串,其參數(shù)由空格分隔。程序 15-17中的buf_args函數(shù)將字符串分解成標(biāo)準(zhǔn)argv型參數(shù)表,并調(diào)用用戶函數(shù)處理參數(shù)。本節(jié)稍后及第18章將用到該函數(shù)。使用ANSI C函數(shù)strtok將字符串分割成參數(shù)。程序15-16 request函數(shù)370UNIX環(huán)境高級(jí)編程程序15-17buf_args函數(shù)第 15章 高級(jí)進(jìn)程間通信371buf_args調(diào)用的服務(wù)器函數(shù)是cli_args(見(jiàn)程序15-18)。它驗(yàn)證客戶機(jī)發(fā)送的參數(shù)是否正確,然后將路徑名和打開(kāi)方式存放在全局變量中。這樣也就完成了open服務(wù)器,它由客戶機(jī)執(zhí)行fork和exec而調(diào)用。在fork之前創(chuàng)建了一個(gè)流管道,然后客戶機(jī)和服務(wù)器用其
22、進(jìn)行通信。在這種安排下,每個(gè)客戶機(jī)都有一服務(wù)器。在下一節(jié)觀察了客戶機(jī)-服務(wù)器連接后,在15.6節(jié)重新實(shí)現(xiàn)一個(gè)open服務(wù)器,其中用一個(gè)精靈進(jìn)程作為服務(wù)器,所有客戶機(jī)都與其進(jìn)行聯(lián)系。程序15-18 cli_args函數(shù)15.5客戶機(jī)-服務(wù)器連接函數(shù)對(duì)于相關(guān)進(jìn)程(例如,父進(jìn)程進(jìn)程)之間的 IPC,流管道非常有用。前節(jié)所述的open服務(wù)器使用未命名的流管道能從子進(jìn)程向父進(jìn)程傳送文件描述符。但是當(dāng)處理無(wú)關(guān)進(jìn)程時(shí)(例如,若服務(wù)器是一精靈進(jìn)程),則需要使用有名的流管道。可以先構(gòu)造一未命名流管道(用s_pipe 函數(shù)),然后對(duì)每一端加上一文件系統(tǒng)路徑名。精靈進(jìn)程服務(wù)器將只創(chuàng)建流管道的一端,并對(duì)該端加上一名字
23、。這樣,無(wú)關(guān)的客戶機(jī)可以向服務(wù)者的流管道端發(fā)送消息,從而與精靈進(jìn)程會(huì)聚。這類似于圖 14-11中所示的情況,在該圖中客戶機(jī)使用FIFO發(fā)送它們的請(qǐng)求。一種更好的方法是:服務(wù)器創(chuàng)建一名字公開(kāi)的流管道的一端,然后客戶機(jī)連接至該端。另外,每次一個(gè)新客戶機(jī)連至服務(wù)器名流管道時(shí),就在客戶機(jī)和服務(wù)器之間創(chuàng)建一條全新的流管道。這樣,每次一個(gè)新客戶機(jī)連接至服務(wù)器,以及客戶機(jī)終止時(shí),服務(wù)器都會(huì)得到通知。 SVR4和4.3+BSD都支持這種形式的IPC。本節(jié)將開(kāi)發(fā)三個(gè)函數(shù),客戶機(jī) -服務(wù)器可以使用這些函數(shù)以建立上述針對(duì)每個(gè)客戶機(jī)的連接。#include ourhdr.h serv_listen(const ch
24、anram*e);返回:若成功則返回為文件描述符,若出錯(cuò)則 0372UNIX環(huán)境高級(jí)編程首先,一個(gè)服務(wù)器應(yīng)當(dāng)宣布,它愿意聽(tīng)取客戶機(jī)在一個(gè)眾所名字上的連接,該名字是在文件系統(tǒng)中的一個(gè)路徑名。為此調(diào)用 serv_listen,其參數(shù)name是服務(wù)器的眾所名字。客戶機(jī)希望與服務(wù)器連接時(shí)使用此名字。該函數(shù)的返回值是命名流管道服務(wù)器端的文件描述符。一旦服務(wù)器已調(diào)用serv_listen,它將調(diào)用serv_accept等待客戶連接到達(dá)。#include ourhdr.h serv_accept(tenfd, uid_t u*idptr);返回:若成功則返回為文件描述符,若出錯(cuò)則 0listenfd是ser
25、v_listen返回的描述符。在客戶機(jī)連接到服務(wù)器眾所的名字上之前,此函數(shù)并不返回。當(dāng)客戶機(jī)連接至服務(wù)器時(shí),自動(dòng)創(chuàng)建一條全新的流管道,其新描述符作為該函數(shù)的值返回。另外,客戶機(jī)的有效用戶ID通過(guò)指針uidptr客戶機(jī)為與服務(wù)器連接只需調(diào)用cli_conn函數(shù)。#include ourhdr.h cli_conn(const ch a nram*e);返回:若成功則返回為文件描述符,若出錯(cuò)則 0客戶指定的name應(yīng)當(dāng)與服務(wù)器調(diào)用serv_listen時(shí)宣布的相同。返回的描述符務(wù)器的流管道連接至服使用上述三個(gè)函數(shù),就可編寫服務(wù)器精靈進(jìn)程,它可以管理任一數(shù)量的客戶機(jī)。唯一的限制是單個(gè)進(jìn)程可用的描述符
26、數(shù),服務(wù)器對(duì)于每一個(gè)客戶機(jī)連接都需要一個(gè)描述符。因?yàn)檫@些函數(shù)處理的都是普通文件描述符,所以服務(wù)器使用 select或poll就可在所有客戶機(jī)之間多路轉(zhuǎn)接 I/O請(qǐng)求。最后,因?yàn)榭蛻魴C(jī)-服務(wù)器連接都是流管道,所以可以經(jīng)由連接傳送打開(kāi)描述符。下面兩節(jié)將說(shuō)明在SVR4和4.3+BSD之下這三個(gè)函數(shù)的實(shí)現(xiàn)。第 18章開(kāi)發(fā)一個(gè)通用的連接服務(wù)器時(shí),也將使用這三個(gè)函數(shù)。15.5.1 SVR4SVR4提供裝配的流以及一個(gè)名為 connld的流處理模塊,用其可以提供與服務(wù)器有唯一連接名流管道。裝配流和connld模塊是由Presotto和Ritchie1990為Researc的,后來(lái)由SVR4采用。IX系統(tǒng)開(kāi)發(fā)
27、首先,服務(wù)器創(chuàng)建一未命名流管道,并將流處理模塊connld壓入一端。圖15-5顯示了這一處理結(jié)果。然后,使壓入 c o n n l d 的一端具有一路徑名。S V R 4 提供f a t t a c h 函數(shù)實(shí)現(xiàn)這一點(diǎn)。任一進(jìn)程(例如客戶機(jī))打開(kāi)此路徑名就名端。該管道程序15-19使用了20余行代碼實(shí)現(xiàn)serv_listen函數(shù)。用戶進(jìn)程流首流首內(nèi)核圖15-5 在一端壓入connld模塊后的流管道第 15章 高級(jí)進(jìn)程間通信373程序15-19SVR4的serv_listen函數(shù)當(dāng)另一進(jìn)程對(duì)管道名端( connld模塊壓入端)調(diào)用open時(shí),發(fā)生下列處理過(guò)程:創(chuàng)建一個(gè)新管道。該新管道的一個(gè)描述符
28、作為open的返回值回送給客戶機(jī)。另一個(gè)描述符在命名管道的另一端(亦即不是壓入 connld的端)傳送給服務(wù)器。服務(wù)器以帶I_RECVFD命令的ioctl接受該新描述符。假定服務(wù)器用fattach函數(shù)加到其管道的眾所調(diào)用:fd=open(/tmp/serv1, O_RDWR); 并返回后產(chǎn)生的結(jié)果。的名字是/tmp/serv1。圖15-6顯示了客戶機(jī)圖15-6 客戶機(jī)-服務(wù)器在命名管道上的連接客戶機(jī)服務(wù)器流首流首流首流首內(nèi)核374UNIX環(huán)境高級(jí)編程客戶機(jī)和服務(wù)器之間的管道是open創(chuàng)建的,被打開(kāi)的路徑名實(shí)際上是一命名管道,其中壓入了connld模塊??蛻魴C(jī)得到由open返回的文件描述符fd。
29、服務(wù)器處的新文件描述符是clifdl,它是由服務(wù)器在描述符fd0上以I_RECVFD命令調(diào)用ioctl而接收到的。一旦服務(wù)器在fd1上壓入了connld模塊,并對(duì)fd1附接上一個(gè)名字,它就不再使用fd1。服務(wù)器調(diào)用程序15-20中的serv_accept函數(shù)等待客戶機(jī)連接到達(dá)。程序15-20 SVR4的serv_accept函數(shù)在圖15-6中,serv_accept的第一個(gè)參數(shù)應(yīng)當(dāng)是描述符fd0,serv_accept的返回值是描述符 clifdl??蛻魴C(jī)調(diào)用程序15-21中的cli_conn函數(shù)起動(dòng)對(duì)服務(wù)器的連接。程序15-21 SVR4的cli_conn函數(shù)對(duì)返回的描述符是否一個(gè)流設(shè)備進(jìn)行
30、了兩次檢查,以便處理服務(wù)器沒(méi)有起動(dòng),但該路徑名卻存在于文件系統(tǒng)中的情況。(在SVR4下,幾乎沒(méi)理由去調(diào)用cli_conn,而不第 15章 高級(jí)進(jìn)程間通信375是直接調(diào)用 open。下一節(jié)將看到,在 BSD系統(tǒng)之下, cli_conn函數(shù)要復(fù)雜得多,因此編寫 cli_conn函數(shù)就很必要。)15.5.2 4.3+BSD在4.3+BSD之下,為了用UNIX域套接口連接客戶機(jī)和服務(wù)器,需要有一套不同的操作函數(shù)。因?yàn)閼?yīng)用socket、bind、listen、accept和connect函數(shù)的大部分細(xì)節(jié)與其他網(wǎng)絡(luò)協(xié)議有關(guān)(參見(jiàn)Stevens1990),所以此處不詳細(xì)展開(kāi)。程序15-22包含了serv_l
31、isten函數(shù)。它是服務(wù)器調(diào)用的第一個(gè)函數(shù)。程序15-224.3+BSD的serv_listen函數(shù)首先,調(diào)用socket函數(shù)創(chuàng)建一個(gè)UNIX域套接口。然后,填充sockeraddr_un結(jié)構(gòu),將一個(gè)眾的路徑名賦與該套接口。該結(jié)構(gòu)是調(diào)用bind函數(shù)的一個(gè)參數(shù)。然后調(diào)用listen以通知內(nèi)核:所本服務(wù)器正等待來(lái)自客戶機(jī)的連接。(listen的第二個(gè)參數(shù)是 5,它是最大的未決連接請(qǐng)求數(shù),因?yàn)镾VR4也支持UNIX域套接口,所以本節(jié)所示代碼同樣可在SVR4之下工作。376UNIX環(huán)境高級(jí)編程內(nèi)核將這些請(qǐng)求對(duì)該描述符進(jìn)行排隊(duì)。大多數(shù)實(shí)現(xiàn)強(qiáng)制該值的上限為 5。)客戶機(jī)調(diào)用cli_conn函數(shù)(見(jiàn)程序15
32、-23)起動(dòng)與服務(wù)器的連接。程序15-23 4.3+BSD的cli_conn函數(shù)第 15章 高級(jí)進(jìn)程間通信377調(diào)用socket函數(shù)以創(chuàng)建客戶端的UNIX域套接口,然后客戶機(jī)的名字填入socketaddr_un結(jié)構(gòu)。該路徑名的最后 5個(gè)字符是客戶機(jī)的進(jìn)程ID(可以查證此結(jié)構(gòu)的長(zhǎng)度是 14個(gè)字符,以避免UNIX域套接口早期實(shí)現(xiàn)的某些錯(cuò)誤)。在路徑名已經(jīng)存在的情況下調(diào)用 unlink,然后再調(diào)用bind將一名字賦與客戶機(jī)的套接口,這就創(chuàng)建了文件系統(tǒng)中的路徑名,該文件的類型是套接口。接著調(diào)用 od,它關(guān)閉除user_read,user_write和user_execute以外的存取權(quán)。在serv_a
33、ccept中,服務(wù)器檢查該套接口的這些權(quán)和用戶ID,以驗(yàn)證用戶的。然后,以服務(wù)器眾所與服務(wù)器的連接。的路徑名填充另一個(gè)socketaddr_un結(jié)構(gòu)。最后, connect函數(shù)起動(dòng)創(chuàng)建每個(gè)客戶機(jī)與服務(wù)器的唯一連接是通過(guò)在 serv_accept函數(shù)中調(diào)用accept函數(shù)實(shí)現(xiàn)的(見(jiàn)程序15-24)。程序15-24 4.3+BSD的serv_accept函數(shù)378UNIX環(huán)境高級(jí)編程服務(wù)器在調(diào)用accept中堵塞以等待客戶機(jī)調(diào)用cli_conn。當(dāng)accept返回時(shí),其返回值是連向客戶機(jī)的全新的描述符(這類似于 S V R 4 中 connld模塊所做的)。另外, accept也通過(guò)其第二個(gè)參數(shù)(
34、指向socketaddr_un結(jié)構(gòu)的指針)返回客戶機(jī)賦與其套接口的路徑名(它包含客戶機(jī)的進(jìn)程ID)。用null字節(jié)結(jié)束此路徑名,然后調(diào)用s。這使個(gè)套接口,其 user_execute??梢则?yàn)證此路徑名確實(shí)是一權(quán) user_read,user_write和也驗(yàn)證與該套接口相關(guān)的三個(gè)時(shí)間不超過(guò)30秒。(time函數(shù)返回自UNIX紀(jì)元經(jīng)過(guò)的時(shí)間和日期,它們都以秒計(jì)。)如果所有這些檢查都通過(guò),則認(rèn)為該客戶機(jī)的(其有效用戶ID)是該套接口的所有者。雖然這種檢查并不完善,但卻是現(xiàn)有系統(tǒng)所能做得最好的。(如果內(nèi)核能像SVR4 I_RECVFD做的那樣,將有效用戶ID返回給accept,那就更好一些。)圖15
35、-7顯示了cli_conn調(diào)用返回后的這種連接,假定服務(wù)器眾所請(qǐng)將此圖與圖15-6相比較。15.6open服務(wù)器第2版的名字是 /tmp/serv1。在15.4節(jié)中,客戶機(jī)調(diào)用fork和exec構(gòu)造了一個(gè)open服務(wù)器,它說(shuō)明了如何從子程序向父程序傳送文件描述符。本節(jié)將開(kāi)發(fā)一個(gè)精靈進(jìn)程樣式的 open服務(wù)器。一個(gè)服務(wù)器處理所有客戶機(jī)的請(qǐng)求。由于避免使用了fork和exec,期望這一設(shè)計(jì)會(huì)更有效的。在客戶機(jī)和服務(wù)器之間仍將使用上一節(jié)說(shuō)明的三個(gè)函數(shù): serv_listen、serv_accept和cli_conn。這一服務(wù)器將表明:一個(gè)服務(wù)器可以處理多個(gè)客戶機(jī),為此使用的技術(shù)是12.5節(jié)中說(shuō)明的
36、select和poll函數(shù)。本節(jié)所述的客戶機(jī)類似于15.4節(jié)中的客戶機(jī)。確實(shí),文件main.c是完全相同的(見(jiàn)程序15-12)。在open h頭文件(見(jiàn)程序15-11)中則加了下面1行:#define CS_OPEN /home/stevens/open /* servers well-known name */ 因?yàn)樵谶@里調(diào)用的是cli_conn而非fork和exec,所以文件open.c與程序15-13完全不同。這示于程序15-25中。程序15-25 csopen函數(shù)客戶機(jī)服務(wù)器套接口套接口套接口內(nèi)核圖15-7 UNIX域套接口上客戶機(jī)-服務(wù)器連接高級(jí)進(jìn)程間通信379第 15章客戶機(jī)與服務(wù)
37、器之間使用的協(xié)議仍然相同。讓先查看服務(wù)器。頭文件opend.h(見(jiàn)程序15-26)包括了標(biāo)準(zhǔn)頭文件,并且說(shuō)明了全局變量和函數(shù)原型。程序15-26open.h頭文件因?yàn)榇朔?wù)器處理所有客戶機(jī),所以它必須保存每個(gè)客戶機(jī)連接的狀態(tài)。這是用定義在opend.h頭文件中的cnt數(shù)組實(shí)現(xiàn)的。程序15-27定義了三個(gè)處理此數(shù)組的函數(shù)。380UNIX環(huán)境高級(jí)編程程序15-27處理cnt數(shù)組的三個(gè)函數(shù)第一次調(diào)用cnt_add時(shí),它調(diào)用cnt_alloc、cnt_alloc又調(diào)用malloc為該數(shù)組的10個(gè)登記項(xiàng)分配空間。在這10個(gè)登記項(xiàng)全部用完后,再調(diào)用cnt_add,使realloc分配附加空間。依靠這種動(dòng)態(tài)
38、空間分配,無(wú)需在編譯時(shí)限制cnt數(shù)組的長(zhǎng)度。第 15章 高級(jí)進(jìn)程間通信381如果出錯(cuò),那么因?yàn)榧俣ǚ?wù)器是精靈進(jìn)程,所以這些函數(shù)調(diào)用log_函數(shù)(見(jiàn)附錄B)。 main函數(shù)(見(jiàn)程序15-28)定義全局變量,處理命令行選擇項(xiàng),然后調(diào)用 loop函數(shù)。如果以-d選擇項(xiàng)調(diào)用服務(wù)器,則它以交互方式運(yùn)行而非精靈進(jìn)程。當(dāng)測(cè)試些服務(wù)器時(shí),使用交互運(yùn)行方式。程序15-28 main函數(shù)loop函數(shù)是服務(wù)器的無(wú)限循環(huán)。給出該函數(shù)的兩種版本。程序 15-29是使用select的一種版本。(在4.3+BSD和SVR4之下工作),程序15-30是使用poll(用于SVR4)的另一種版本。程序15-29 使用selec
39、t的loop函數(shù)382UNIX環(huán)境高級(jí)編程此函數(shù)調(diào)用serv_listen以創(chuàng)建服務(wù)器對(duì)于客戶機(jī)連接的端點(diǎn)。此函數(shù)的其余部分是一個(gè)循環(huán),它以select調(diào)用開(kāi)始。在select返回后,兩個(gè)條件可能為真:(1) 描述符listenfd可能準(zhǔn)備好讀,這意味著新客戶機(jī)已調(diào)用了cli_conn。為了處理這種情況。調(diào)用serv_accept,然后更新cnt數(shù)組以及與該新客戶機(jī)相關(guān)的簿記消息。(作為select第一個(gè)參數(shù)的最高描述符。也使用中的cnt數(shù)組的最高下標(biāo)。)(2) 一個(gè)現(xiàn)存的客戶機(jī)的連接可能準(zhǔn)備好讀。這意味這下列兩事件之一:(a)該客戶機(jī)已經(jīng)終止,或( b)該客戶機(jī)已發(fā)送一新請(qǐng)求。如果 read返回0(文件結(jié)束),則可認(rèn)為一客戶機(jī)終止。如果讀返回值大于0則可判定有一新請(qǐng)求需處理,調(diào)用request處理此新的客戶機(jī)請(qǐng)求。用allset描述符集當(dāng)前使用的描述符。當(dāng)新客戶機(jī)連至服務(wù)器時(shí),此描述符集的適當(dāng)位被打開(kāi)。當(dāng)該客戶機(jī)終止時(shí),適當(dāng)位就被關(guān)閉。因?yàn)榭蛻魴C(jī)的所有描述符都由內(nèi)核自動(dòng)關(guān)閉(包括與服
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 寧波衛(wèi)生職業(yè)技術(shù)學(xué)院《服務(wù)營(yíng)銷實(shí)務(wù)》2023-2024學(xué)年第二學(xué)期期末試卷
- 四川省成都市雙流區(qū)雙流棠湖中學(xué)2025年高考模擬信息考試數(shù)學(xué)試題(四)含解析
- 遼寧省沈陽(yáng)市實(shí)驗(yàn)中學(xué)2024-2025學(xué)年高三五月模擬考試物理試題試卷含解析
- 烏海職業(yè)技術(shù)學(xué)院《緬甸國(guó)情資料收集與分析中緬雙語(yǔ)》2023-2024學(xué)年第二學(xué)期期末試卷
- 新疆輕工職業(yè)技術(shù)學(xué)院《東方管理學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 上海市嘉定區(qū)封浜高級(jí)中學(xué)2025屆高三下期初考試英語(yǔ)試題含解析
- 武漢地區(qū)十一校2025屆初三月考(一)英語(yǔ)試題含答案
- 咸陽(yáng)市武功縣2024-2025學(xué)年數(shù)學(xué)三下期末學(xué)業(yè)質(zhì)量監(jiān)測(cè)模擬試題含解析
- 江蘇省鹽城市大豐區(qū)第一共同體達(dá)標(biāo)名校2025屆初三第一次適應(yīng)性測(cè)試自選模塊試題含解析
- 凱里學(xué)院《理論力學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 2025屆高考作文寫作素材:6月時(shí)事熱點(diǎn)素材(適用話題+運(yùn)用示例)
- 公對(duì)公車輛租賃合同范本
- 普通植物病理學(xué)智慧樹(shù)知到期末考試答案章節(jié)答案2024年?yáng)|北農(nóng)業(yè)大學(xué)
- DZ∕T 0207-2020 礦產(chǎn)地質(zhì)勘查規(guī)范 硅質(zhì)原料類(正式版)
- 家庭農(nóng)場(chǎng)經(jīng)營(yíng)與管理-家庭農(nóng)場(chǎng)財(cái)務(wù)管理
- 招標(biāo)代理服務(wù)技術(shù)方案
- 《德伯家的苔絲》
- 山姆會(huì)員商店?duì)I銷策略調(diào)查研究
- 寧德時(shí)代入職測(cè)評(píng)試題答案
- 《材料與社會(huì)》課件
- 2024新版:普通話測(cè)試50篇朗讀范文短文(2024年1月1日啟用)
評(píng)論
0/150
提交評(píng)論