




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
15unix環(huán)境高級編程15unix環(huán)境高級編程15unix環(huán)境高級編程下載第15章高級進(jìn)度間通信序言上一章說了然各種UNIX系統(tǒng)供應(yīng)的IPC經(jīng)典方法,包括:管道、FIFO、信息隊(duì)列、信號(hào)量和共享儲(chǔ)藏。本章介紹某些高級的IPC以及它們的應(yīng)用方法,包括:流管道和命紳士管道。使用這些體系,能夠在進(jìn)度間傳達(dá)打開文件描述符。在分別為每一個(gè)客戶進(jìn)度供應(yīng)一個(gè)通道的系統(tǒng)中,這些通信體系使客戶進(jìn)度能與精靈服務(wù)進(jìn)度會(huì)合。4.2BSD和最早供應(yīng)這些高級形式的IPC,但是到此刻還沒有廣泛使用,也缺少參照文件。本章中很多思想來自Pressotto和Ritchie〔1990〕的論文。流管道流管道是一個(gè)雙向(全雙工)管道。單個(gè)流管道就能向父、子進(jìn)度供應(yīng)雙向的數(shù)據(jù)流。圖15-1顯示了觀察流管道的兩種方式。它與圖14-1的唯一差異是雙向箭頭連線,由于流管道是全雙工的。用戶進(jìn)度用戶進(jìn)度或流管通內(nèi)核圖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。(下面將說明該函數(shù)的SVR4和4.3+BSD版本。)程序15-1用流管道驅(qū)動(dòng)add2過濾進(jìn)度的程序356UNIX環(huán)境高級編程下載父程序只使用fd[0],子程序只使用fd[1]。由于流管道的每一端都是全雙工的,因此父進(jìn)度讀、寫fd[0],而子程序?qū)d[1]復(fù)制到標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出。圖15-2顯示了由此構(gòu)成的描述符。下載第15章高級進(jìn)度間通信357s_pipe函數(shù)定義為與標(biāo)準(zhǔn)pipe函數(shù)近似。它的調(diào)父進(jìn)度子進(jìn)度(協(xié)作進(jìn)度)用參數(shù)與pipe同樣,但返回的描述符以讀-寫方式打開。實(shí)例—SVR4下的s_pipe函數(shù)圖15-2為協(xié)作進(jìn)度安排的描述符程序15-2是s_pipe函數(shù)的SVR4版本。它可是調(diào)用創(chuàng)辦全雙工管道的標(biāo)準(zhǔn)pipe函數(shù)。程序15-2s_pipe函數(shù)的SVR4版本在系統(tǒng)V的早期版本中也能夠創(chuàng)辦流管道,但要進(jìn)行的辦理很多。相關(guān)在下創(chuàng)辦流管道的詳細(xì)情況,請參閱Stevens〔1990〕。圖15-3顯示了SVR4之下管道的基本構(gòu)造。它主若是兩個(gè)相互連接的流首。由于管道是一種流設(shè)施,故可將辦理模塊壓入管道的任一一端。節(jié)將用此技術(shù)供應(yīng)一個(gè)能夠裝置的命名管道。實(shí)例—4.3+BSD之下的s_pipe函數(shù)程序15-3是s_pipe函數(shù)的BSD版本。此函數(shù)在4.2BSD及今后的各版本中起作用。它創(chuàng)辦一對互連的UNIX域流套接口。
用戶進(jìn)度流首流首內(nèi)核圖15-3SVR4之下的管道自4.2BSD開始,老例的管道已用此方式實(shí)現(xiàn)。但是,當(dāng)調(diào)用pipe時(shí),第一個(gè)描述符的寫端和第二個(gè)描述符的讀端都被關(guān)閉。為獲得全雙工管道,必定直接調(diào)用socketpair。程序15-3s_pipe函數(shù)的BSD版本358UNIX環(huán)境高級編程下載15.3傳達(dá)文件描述符在進(jìn)度間傳達(dá)打開文件描述符的能力特別適用。用此能夠?qū)蛻魴C(jī)/服務(wù)器應(yīng)用進(jìn)行不同樣的設(shè)計(jì)。它贊同一個(gè)進(jìn)度(一般是服務(wù)器)辦理與打開一個(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ù)。打開文件或設(shè)施的所有細(xì)節(jié)對客戶而言都是透明的。4.2BSD支持傳達(dá)打開描述符,但其推行中有些錯(cuò)誤。4.3BSD消除了這些錯(cuò)誤。及以上版本都支持傳達(dá)打開描述符。下面進(jìn)一步說明“從一個(gè)進(jìn)度向另一個(gè)進(jìn)度傳達(dá)一打開文件描述符”的含義。回憶圖3-2,其中顯示了兩個(gè)進(jìn)度,它們打開了同一文件。誠然它們共享同一v節(jié)點(diǎn)表,但每個(gè)進(jìn)度都有它自己的文件表項(xiàng)。當(dāng)從一個(gè)進(jìn)度向另一個(gè)進(jìn)度傳達(dá)一打開文件描述符時(shí),我們想要發(fā)送進(jìn)度和接收進(jìn)度共享同一文件表項(xiàng)。圖15-4顯示了所希望的安排。在技術(shù)上,發(fā)送進(jìn)度實(shí)質(zhì)上向接受進(jìn)度傳達(dá)一個(gè)指向一打開文件表項(xiàng)的指針。該指針被分配存放在接收進(jìn)度的第一個(gè)可用描述符項(xiàng)中。(注意,不要獲得錯(cuò)覺以為發(fā)送進(jìn)度和接收進(jìn)度中的描述符編號(hào)是同樣的,平時(shí)它們是不同樣的。)這類情況與在fork此后,父、子進(jìn)度完好共享一個(gè)打開文件表項(xiàng)同樣(見圖8-1)。當(dāng)發(fā)送進(jìn)度將描述符傳達(dá)給接收進(jìn)度后,平時(shí)它關(guān)閉該描述符。發(fā)送進(jìn)度關(guān)閉該描述符其實(shí)不造成關(guān)閉該文件或設(shè)施,其原因是該描述符對應(yīng)的文件仍需為接收進(jìn)度打開(即使接收進(jìn)度還沒有接收到該描述符)。進(jìn)度表項(xiàng)fd標(biāo)志ptr文件表文件狀態(tài)標(biāo)志當(dāng)前文件位移v節(jié)點(diǎn)表節(jié)點(diǎn)指針v節(jié)點(diǎn)信息進(jìn)度表項(xiàng)i節(jié)點(diǎn)信息fd標(biāo)志ptr當(dāng)前文件長度圖15-4從上一進(jìn)度傳達(dá)一個(gè)打開文件至下一進(jìn)度第15章高級進(jìn)度間通信359下載下面定義本章使用的三個(gè)函數(shù)(第18章也將使用)以發(fā)送和接收文件描述符。本節(jié)將會(huì)給出關(guān)于SVR4和4.3+BSD的這三個(gè)函數(shù)的不同樣實(shí)現(xiàn)。#include"ourhdr.h"intsend_fd(intintsend_err(int
spipefd,intspipefd,int
filedes);status,constchar*
errmsg);兩個(gè)函數(shù)返回:若成功則為
0,若出錯(cuò)則為
-1intrecv_fd(int
spipefd,ssize_t(*
userfunc)(int,constvoid*,size_t));返回:若成功則為文件描述符,若出錯(cuò)則
<0當(dāng)一個(gè)進(jìn)度(平時(shí)是服務(wù)器)希望將一個(gè)描述符傳達(dá)給另一個(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和status字節(jié)。status的值應(yīng)在-1~-255之間客戶機(jī)調(diào)用recv_fd接收一描述符。若是所有正常(發(fā)送者調(diào)用了send_fd),則作為函數(shù)值返回非負(fù)描述符。否則,返回值是由send_err發(fā)送的status(-1~-255之間的一個(gè)值)。別的,若是服務(wù)器發(fā)送了一條出錯(cuò)信息,則客戶機(jī)調(diào)用它自己的userfunc辦理該信息。userfunc的第一個(gè)參數(shù)是常數(shù)STDERR_FILENO,爾后是指向出錯(cuò)信息的指針及其長度。客戶機(jī)常將userfunc指定為UNIX的write函數(shù)。我們實(shí)現(xiàn)了用于這三個(gè)函數(shù)的我們自己擬定的協(xié)議。為發(fā)送一描述符,send_fd先發(fā)送兩個(gè)0字節(jié),爾后是實(shí)質(zhì)描述符。為了發(fā)送一條出錯(cuò)信息,send_err發(fā)送errmsg,爾后是1個(gè)0字節(jié),最后是status字節(jié)的絕對值(1~255)。recv_fd讀流管道中所有字節(jié)直至null字符。null字符以前的所有字符都送給調(diào)用者的userfunc。recv_fd讀到的下一個(gè)字節(jié)是status字節(jié)。若status字節(jié)為0,那么一個(gè)描述符已傳達(dá),否則表示沒有接收到描述符.send_err函數(shù)在將出錯(cuò)信息寫到流管道后,即調(diào)用send_fd函數(shù)。這示于程序15-4中。程序15-4send_err函數(shù)360UNIX環(huán)境高級編程下載以下三節(jié)介紹了在SVR4、4.3BSD和4.3+BSD下,兩個(gè)函數(shù)send_fd和recv_fd的實(shí)質(zhì)實(shí)現(xiàn)。SVR4在SVR4之下,文件描述符用兩個(gè)ioctl命令在一流管道中交換,這兩個(gè)命令是:I_SENDFD和I_RECVFD。為了發(fā)送一描述符,將ioctl的第三個(gè)參數(shù)設(shè)置為實(shí)質(zhì)描述符。這示于程序15-5中。程序15-5SVR4的send_fd函數(shù)當(dāng)接收一描述符時(shí),ioctl的第三個(gè)參數(shù)是一指向strrecvfd構(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ā)來的,也許獲得一條出錯(cuò)信息。這示于程序15-6中。程序15-6SVR4的recv_fd函數(shù)第15章高級進(jìn)度間通信361下載不幸的是,關(guān)于以及在其基礎(chǔ)上構(gòu)造的SunOS和Ultrix,以及從4.3BSDReno開始的后續(xù)版本必定供應(yīng)不同樣的實(shí)現(xiàn)。為了交換文件描述符,調(diào)用sendmsg(2)和recvmsg(2)函數(shù)。這兩個(gè)函數(shù)的參數(shù)中都有一個(gè)指向msghd的r指針,該構(gòu)造包括了所相關(guān)于要發(fā)送和接收信息的信息。該構(gòu)造定義在<sys/socket.h>頭文件中,在之下,其樣式是:362UNIX環(huán)境高級編程下載頭兩個(gè)元素平時(shí)用于在網(wǎng)絡(luò)連接上發(fā)送數(shù)據(jù)報(bào)文,在這里,目的地址能夠由每個(gè)數(shù)據(jù)報(bào)文指定。下面兩個(gè)元素使我們能夠指定緩存的數(shù)組(散布讀和齊聚寫),這仿佛對readv和writev函數(shù)(見節(jié))的說明同樣。最后兩個(gè)元素辦理存取權(quán)的傳達(dá)和接收。當(dāng)前獨(dú)必然義的存取權(quán)是文件描述符。存取權(quán)僅可超越一個(gè)UNIX域套接口傳送(即在之下作為流管道所使用的)。為了發(fā)送或接收一文件描述符,將msg_accrights設(shè)置為指向該整型描述符,將msg_accrightslen設(shè)置為描述符的長度(即整型的長度)。僅當(dāng)此長度非0時(shí),才傳達(dá)或接收描述符。程序15-7是4.3BSD的send_fd函數(shù)。程序15-7的send_fd函數(shù)第15章高級進(jìn)度間通信363下載在sendmsg調(diào)用中,發(fā)送雙字節(jié)協(xié)議數(shù)據(jù)(null和status字節(jié))和描述符。為了接收一文件描述符,從流管道讀,直至讀到null字節(jié),它位于最后的status字節(jié)以前。null字節(jié)以前是一條出錯(cuò)信息,它來自覺送者。這示于程序15-8。程序15-8的recv_fd函數(shù)364UNIX環(huán)境高級編程下載注意,該程序總是準(zhǔn)備接收一描述符(在每次調(diào)用recvmsg以前,設(shè)置msg_accrights和msg_accrightslen),但是僅當(dāng)在返回時(shí)msg_accrightslen非0,才確實(shí)接收到一描述符。4.3+BSD從4.3BSDReno開始,更正了msghdr構(gòu)造的定義。在以前版本中被稱之為“存取權(quán)”的最后兩個(gè)元素改稱為“輔助數(shù)據(jù)”。別的,在該構(gòu)造結(jié)束處增加了一個(gè)新成員msg_flags。此刻,msg_control字段指向一個(gè)cmsghdr(控制信息頭)構(gòu)造。為了發(fā)送一文件描述符,將cmsg_len設(shè)置為cmsghdr構(gòu)造長度加一個(gè)整型(描述符)的長度。將cmsg_level設(shè)置為SOL_SOCKET,cmsg_type設(shè)置為SCM_RIGHTS,這表示正在傳達(dá)的是存取權(quán)(SCM表示套接口級控制信息)。實(shí)質(zhì)描述符的存放地址緊隨在cmsy_type字段此后,使用CMSG_DATA宏以獲得指向該整型數(shù)的指針。程序15-9示出了4.3BSDReno之下的send_fd函數(shù)。程序15-9的send_fd函數(shù)第15章高級進(jìn)度間通信365下載為了接收一描述符(見程序15-10),我們?yōu)閏msghdr構(gòu)造和一描述符分配了足夠的儲(chǔ)藏區(qū),設(shè)置
msg_control使其指向所分配到的儲(chǔ)藏區(qū),爾后調(diào)用
recvmsg。程序15-104.3BSDReno
的
recv_fd
函數(shù)366UNIX環(huán)境高級編程下載open服務(wù)器第1版當(dāng)前,使用文件描述符傳達(dá)技術(shù)開發(fā)了一個(gè)open服務(wù)器:它是一個(gè)可執(zhí)行程序,由一個(gè)進(jìn)度執(zhí)行以打開一個(gè)或多個(gè)文件。該服務(wù)器不是將文件送回調(diào)用進(jìn)度,而是送回一個(gè)打開文件描述符。這使該服務(wù)器對任何種類的文件(比方調(diào)制解調(diào)器線或網(wǎng)絡(luò)連接)而不只是一般文件都能起作用。這也意味著,用IPC交換最小量的信息—從客戶機(jī)到服務(wù)器傳達(dá)文件名和打開方式,而從服務(wù)器到客戶機(jī)返回描述符。文件內(nèi)容則不需用IPC傳達(dá)。將服務(wù)器設(shè)計(jì)成一個(gè)單獨(dú)的可執(zhí)行程序有很多優(yōu)點(diǎn):任一客戶機(jī)都易于和服務(wù)器聯(lián)系,這近似于客戶機(jī)調(diào)用一庫函數(shù)。不需要將一特定服務(wù)編碼在應(yīng)用程序中,而是設(shè)計(jì)一種可供重用的設(shè)施。如若需要更正服務(wù)器,那么也只影響一個(gè)程序。相反,更新一庫函數(shù)可能要更正調(diào)用此庫函數(shù)的所有程序(用連編程序重新連接)。共享庫函數(shù)能夠簡化這類更新。服務(wù)器能夠是設(shè)置-用戶-ID程序,于是使其擁有客戶機(jī)沒有的附加贊同權(quán)。注意,一第15章高級進(jìn)度間通信367下載個(gè)庫函數(shù)(或共享庫函數(shù))不能夠供應(yīng)這類能力。客戶機(jī)創(chuàng)辦一流管道,爾后調(diào)用fork和exec以調(diào)用服務(wù)器??蛻魴C(jī)經(jīng)流管道發(fā)送央求,服務(wù)器經(jīng)管道回送響應(yīng)。定義客戶機(jī)和服務(wù)器間的協(xié)議以下:客戶機(jī)經(jīng)流管道向服務(wù)器發(fā)送以下形式的央求:open<pathname><openmode>0<openmode>是open函數(shù)的第二個(gè)參數(shù),以十進(jìn)制表示。該央求字符串以null字節(jié)結(jié)尾。服務(wù)器調(diào)用send_fd或send_err回送一打開描述符或一條出錯(cuò)信息。這是一個(gè)進(jìn)度向其父進(jìn)度發(fā)送一打開描述符的實(shí)例。節(jié)將更正此實(shí)例,其中使用了一個(gè)精靈服務(wù)器,它將一個(gè)描述符發(fā)送給完好沒關(guān)的進(jìn)度。程序15-11是頭文件,它包括標(biāo)準(zhǔn)系統(tǒng)頭文件,并且定義了各個(gè)函數(shù)原型。程序15-11open.h頭文件程序15-12是main函數(shù),其中包括一個(gè)循環(huán),它先從標(biāo)準(zhǔn)輸入讀一個(gè)路徑名,爾后將該文件復(fù)制至標(biāo)準(zhǔn)輸出。它調(diào)用函數(shù)csopen以與open服務(wù)器聯(lián)系,從其返回一打開描述符。程序15-12main函數(shù)368UNIX環(huán)境高級編程下載程序15-13是函數(shù)csopen,它先創(chuàng)辦一流管道,爾后進(jìn)行服務(wù)器的fork和exec操作。程序15-13csopen函數(shù)子進(jìn)度關(guān)閉管道的一端,父進(jìn)度關(guān)閉另一端。子進(jìn)度也為它所執(zhí)行的服務(wù)器將管道的一端復(fù)制到其標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出0(另一種可選擇的方案是將描述符fd[1]的ASCII表示形式作為一個(gè)參數(shù)傳達(dá)給服務(wù)器。)父進(jìn)度將央求發(fā)送給服務(wù)器,央求中包括路徑名和打開方式。最后,父進(jìn)度調(diào)用recv_fd以返回描述符或錯(cuò)誤信息。若是服務(wù)器返回一錯(cuò)誤信息則調(diào)用write,向標(biāo)準(zhǔn)出錯(cuò)輸出該信息。此刻,觀察open服務(wù)器。其程序是opend,它由子進(jìn)度執(zhí)行(見程序15-13)。先觀察第15章高級進(jìn)度間通信369下載頭文件(見程序15-14),它包括了系統(tǒng)頭文件,并且說了然全局變量和函數(shù)原型。程序15-14頭文件main函數(shù)(見程序15-15)經(jīng)流管道(它的標(biāo)準(zhǔn)輸入)讀來自客戶機(jī)的央求,爾后調(diào)用函數(shù)request。程序15-15main函數(shù)程序15-16中的request函數(shù)肩負(fù)所有工作。它調(diào)用函數(shù)buf_args將客戶機(jī)央求分解成標(biāo)準(zhǔn)argv型的參數(shù)表,爾后調(diào)用函數(shù)cli_args辦理客戶機(jī)的參數(shù)。若是所有正常,則調(diào)用open打開相應(yīng)文件,接著調(diào)用send_fd,經(jīng)由流管道(它的標(biāo)準(zhǔn)輸出)將描述符回送給客戶機(jī)。若是出錯(cuò)則調(diào)用send_err回送一則出錯(cuò)信息,其中使用了前面說明的客戶機(jī)-服務(wù)器協(xié)議??蛻魴C(jī)央求是一個(gè)空的中斷的字符串,其參數(shù)由空格分開。程序15-17中的buf_args函數(shù)將字符串分解成標(biāo)準(zhǔn)argv型參數(shù)表,并調(diào)用用戶函數(shù)辦理參數(shù)。本節(jié)稍后及第18章將用到該函數(shù)。我們使用ANSIC函數(shù)strtok將字符串切割成參數(shù)。程序15-16request函數(shù)370UNIX環(huán)境高級編程下載程序15-17buf_args函數(shù)第15章高級進(jìn)度間通信371下載buf_args調(diào)用的服務(wù)器函數(shù)是cli_args(見程序15-18)。它考據(jù)客戶機(jī)發(fā)送的參數(shù)可否正確,爾后將路徑名和打開方式存放在全局變量中。這樣也就完成了open服務(wù)器,它由客戶機(jī)執(zhí)行fork和exec而調(diào)用。在fork以前創(chuàng)辦了一個(gè)流管道,爾后客戶機(jī)和服務(wù)器用其進(jìn)行通信。在這類安排下,每個(gè)客戶機(jī)都有一服務(wù)器。在下一節(jié)觀察了客戶機(jī)-服務(wù)器連接后,我們將在節(jié)重新實(shí)現(xiàn)一個(gè)open服務(wù)器,其中用一個(gè)精靈進(jìn)度作為服務(wù)器,所有客戶機(jī)都與其進(jìn)行聯(lián)系。程序15-18cli_args函數(shù)客戶機(jī)-服務(wù)器連接函數(shù)關(guān)于相關(guān)進(jìn)度(比方,父進(jìn)度和子進(jìn)度)之間的IPC,流管道特別適用。前節(jié)所述的open服務(wù)器使用未命名的流管道能從子進(jìn)度向父進(jìn)度傳達(dá)文件描述符。但是當(dāng)辦理沒關(guān)進(jìn)度時(shí)(例如,若服務(wù)器是一精靈進(jìn)度),則需要使用有名的流管道。能夠先構(gòu)造一未命紳士管道(用s_pipe函數(shù)),爾后對每一端加上一文件系統(tǒng)路徑名。精靈進(jìn)度服務(wù)器將只創(chuàng)辦流管道的一端,并對該端加上一名字。這樣,沒關(guān)的客戶機(jī)能夠向服務(wù)者的流管道端發(fā)送信息,從而與精靈進(jìn)度匯聚。這近似于圖14-11中所示的情況,在該圖中客戶機(jī)使用FIFO發(fā)送它們的央求。一種更好的方法是:服務(wù)器創(chuàng)辦一名字公開的流管道的一端,爾后客戶機(jī)連接至該端。別的,每次一個(gè)新客戶機(jī)連至服務(wù)器的命紳士管道時(shí),就在客戶機(jī)和服務(wù)器之間創(chuàng)辦一條嶄新的流管道。這樣,每次一個(gè)新客戶機(jī)連接至服務(wù)器,以及客戶機(jī)停止時(shí),服務(wù)器都會(huì)獲得通知。SVR4和4.3+BSD都支持這類形式的IPC。本節(jié)將開發(fā)三個(gè)函數(shù),客戶機(jī)-服務(wù)器能夠使用這些函數(shù)以建立上述針對每個(gè)客戶機(jī)的連接。#include"ourhdr.h"intserv_listen(constchar*name);返回:若成功則返回為文件描述符,若出錯(cuò)則<0372UNIX環(huán)境高級編程下載第一,一個(gè)服務(wù)器應(yīng)當(dā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"intserv_accept(intlistenfd,uid_t*uidptr);返回:若成功則返回為文件描述符,若出錯(cuò)則<0istenfd是serv_listen返回的描述符。在客戶機(jī)連接到服務(wù)器眾所周知的名字上以前,此函數(shù)其實(shí)不返回。當(dāng)客戶機(jī)連接至服務(wù)器時(shí),自動(dòng)創(chuàng)辦一條嶄新的流管道,其新描述符作為該函數(shù)的值返回。別的,客戶機(jī)的有功能戶ID經(jīng)過指針uidptr儲(chǔ)藏??蛻魴C(jī)為與服務(wù)器連接只需調(diào)用cli_conn函數(shù)。#include"ourhdr.h"intcli_conn(constchar*
name);返回:若成功則返回為文件描述符,若出錯(cuò)則
<0客戶指定的name應(yīng)當(dāng)與服務(wù)器調(diào)用serv_listen時(shí)宣布的同樣。返回的描述符引用連接至服務(wù)器的流管道使用上述三個(gè)函數(shù),即可編寫服務(wù)器精靈進(jìn)度,它能夠管理任一數(shù)量的客戶機(jī)。唯一的限制是單個(gè)進(jìn)度可用的描述符數(shù),服務(wù)器關(guān)于每一個(gè)客戶機(jī)連接都需要一個(gè)描述符。由于這些函數(shù)辦理的都是一般文件描述符,因此服務(wù)器使用select或poll即可在所有客戶機(jī)之間多路轉(zhuǎn)接I/O央求。最后,由于客戶機(jī)-服務(wù)器連接都是流管道,因此能夠經(jīng)由連接傳達(dá)打開描述符。下面兩節(jié)將說明在SVR4和4.3+BSD之下這三個(gè)函數(shù)的實(shí)現(xiàn)。第18章開發(fā)一個(gè)通用的連接服務(wù)器時(shí),也將使用這三個(gè)函數(shù)。SVR4SVR4供應(yīng)裝置的流以及一個(gè)名為connld的流辦理模塊,用其能夠供應(yīng)與服務(wù)器有唯一連接的命紳士管道。裝置流和connld模塊是由Presotto和Ritchie[1990]為ResearchUNIX系統(tǒng)開發(fā)的,后出處SVR4采用。用戶進(jìn)度第一,服務(wù)器創(chuàng)辦一未命紳士管道,并將流處理模塊connld壓入一端。圖15-5顯示了這一辦理結(jié)果。爾后,使壓入connl的d一端擁有一路徑名。流首流首SVR4供應(yīng)fattac函h數(shù)實(shí)現(xiàn)這一點(diǎn)。任一進(jìn)度內(nèi)核(比方客戶機(jī))打開此路徑名就引用該管道的命名端。程序15-19使用了20余行代碼實(shí)現(xiàn)serv_listen函數(shù)。圖15-5在一端壓入connld模塊后的流管道下載第15章高級進(jìn)度間通信373程序15-19SVR4的serv_listen函數(shù)當(dāng)另一進(jìn)度對管道的命名端(connld模塊壓入端)調(diào)用open時(shí),發(fā)生以下辦理過程:創(chuàng)辦一個(gè)新管道。該新管道的一個(gè)描述符作為open的返回值回送給客戶機(jī)。另一個(gè)描述符在命名管道的另一端(亦即不是壓入connld的端)傳達(dá)給服務(wù)器。服務(wù)器以帶I_RECVFD命令的ioctl接受該新描述符。假定服務(wù)器用fattach函數(shù)加到其管道的眾所周知的名字是/tmp/serv1。圖15-6顯示了客戶機(jī)調(diào)用:fd=open("/tmp/serv1",O_RDWR);并返回后產(chǎn)生的結(jié)果??蛻魴C(jī)服務(wù)器流首流首流首流首內(nèi)核圖15-6客戶機(jī)-服務(wù)器在命名管道上的連接374UNIX環(huán)境高級編程下載客戶機(jī)和服務(wù)器之間的管道是open創(chuàng)辦的,被打開的路徑名實(shí)際上是一命名管道,其中壓入了connld模塊??蛻魴C(jī)獲得由open返回的文件描述符fd。服務(wù)器處的新文件描述符是clifdl,它是由服務(wù)器在描述符fd[0]上以I_RECVFD命令調(diào)用ioctl而接收到的。一旦服務(wù)器在fd[1]上壓入了connld模塊,并對fd[1]附接上一個(gè)名字,它就不再使用fd[1]。服務(wù)器調(diào)用程序15-20中的serv_accept函數(shù)等待客戶機(jī)連接到達(dá)。程序15-20SVR4的serv_accept函數(shù)在圖15-6中,serv_accept的第一個(gè)參數(shù)應(yīng)當(dāng)是描述符fd[0],serv_accept的返回值是描述符clifdl??蛻魴C(jī)調(diào)用程序15-21中的cli_conn函數(shù)起動(dòng)對服務(wù)器的連接。程序15-21SVR4的cli_conn函數(shù)我們對返回的描述符可否引用一個(gè)流設(shè)施進(jìn)行了兩次檢查,以便辦理服務(wù)器沒有起動(dòng),但該路徑名卻存在于文件系統(tǒng)中的情況。(在SVR4下,幾乎沒有什么原因去調(diào)用cli_conn,而不下載
第15章高級進(jìn)度間通信375是直接調(diào)用open。下一節(jié)將看到,在BSD系統(tǒng)之下,cli_conn函數(shù)要復(fù)雜得多,因此編寫cli_conn函數(shù)就很必要。)4.3+BSD在4.3+BSD之下,為了用UNIX域套接口連接客戶機(jī)和服務(wù)器,需要有一套不同樣的操作函數(shù)。由于應(yīng)用socket、bind、listen、accept和connect函數(shù)的大多數(shù)細(xì)節(jié)與其他網(wǎng)絡(luò)協(xié)議相關(guān)(拜會(huì)Stevens〔1990〕),因此此處不詳細(xì)張開。由于SVR4也支持UNIX域套接口,因此本節(jié)所示代碼同樣可在SVR4之下工作。程序15-22包括了serv_listen函數(shù)。它是服務(wù)器調(diào)用的第一個(gè)函數(shù)。程序15-224.3+BSD的serv_listen函數(shù)第一,調(diào)用socket函數(shù)創(chuàng)辦一個(gè)UNIX域套接口。爾后,填充sockeraddr_un構(gòu)造,將一個(gè)眾所周知的路徑名賦與該套接口。該構(gòu)造是調(diào)用bind函數(shù)的一個(gè)參數(shù)。爾后調(diào)用listen以通知內(nèi)核:本服務(wù)器正等待來自客戶機(jī)的連接。(listen的第二個(gè)參數(shù)是5,它是最大的未決連接央求數(shù),376UNIX環(huán)境高級編程下載內(nèi)核將這些央求對該描述符進(jìn)行排隊(duì)。大多數(shù)實(shí)現(xiàn)逼迫該值的上限為5。)客戶機(jī)調(diào)用cli_conn函數(shù)(見程序15-23)起動(dòng)與服務(wù)器的連接。程序15-234.3+BSD的cli_conn函數(shù)下載第15章高級進(jìn)度間通信377調(diào)用socket函數(shù)以創(chuàng)辦客戶端的UNIX域套接口,爾后客戶機(jī)專用的名字填入socketaddr_un構(gòu)造。該路徑名的最后5個(gè)字符是客戶機(jī)的進(jìn)度ID(我們能夠查證此構(gòu)造的長度是14個(gè)字符,以防備UNIX域套接口早期實(shí)現(xiàn)的某些錯(cuò)誤)。在路徑名已經(jīng)存在的情況下調(diào)用unlink,爾后再調(diào)用bind將一名字賦與客戶機(jī)的套接口,這就創(chuàng)辦了文件系統(tǒng)中的路徑名,該文件的種類是套接口。接著調(diào)用chmod,它關(guān)閉除user_read,user_write和user_execute以外的存取權(quán)。在serv_accept中,服務(wù)器檢查該套接口的這些贊同權(quán)和用戶ID,以考據(jù)用戶的身份。爾后,以服務(wù)器眾所周知的路徑名填充另一個(gè)socketaddr_un構(gòu)造。最后,connect函數(shù)起動(dòng)與服務(wù)器的連接。創(chuàng)辦每個(gè)客戶機(jī)與服務(wù)器的唯一連接是經(jīng)過在serv_accept函數(shù)中調(diào)用accept函數(shù)實(shí)現(xiàn)的(見程序15-24)。程序15-244.3+BSD
的serv_accept函數(shù)378UNIX環(huán)境高級編程下載服務(wù)器在調(diào)用accept中擁堵以等待客戶機(jī)調(diào)用客戶機(jī)的嶄新的描述符(這近似于SVR4中connld模塊所做的)。別的,accept也經(jīng)過其第二個(gè)參數(shù)(指向socketaddr_un構(gòu)造的指針)返回客戶機(jī)賦與其套接口的路徑名(它包括客戶機(jī)的進(jìn)度ID)。用null字節(jié)結(jié)束此路徑名,爾后調(diào)用stat。這使我們能夠考據(jù)此路徑名確實(shí)是一個(gè)套接口,其贊同權(quán)user_read,user_write和user_execute。我們也考據(jù)與該套接口相關(guān)的三
cli_conn。當(dāng)accept返回時(shí),其返回值是連向客戶機(jī)服務(wù)器套接口套接口套接口內(nèi)核圖15-7UNIX域套接口上客戶機(jī)-服務(wù)器連接個(gè)時(shí)間不高出30秒。(time函數(shù)返回自UNIX紀(jì)元經(jīng)過的時(shí)間和日期,它們都以秒計(jì)。)若是所有這些檢查都經(jīng)過,則以為該客戶機(jī)的身份(其有功能戶ID)是該套接口的所有者。誠然這類檢查其實(shí)不完滿,但倒是現(xiàn)有系統(tǒng)所能做得最好的。(若是內(nèi)核能像SVR4I_RECVFD做的那樣,將有功能戶ID返回給accept,那就更好一些。)圖15-7顯示了cli_conn調(diào)用返回后的這類連接,假定服務(wù)器眾所周知的名字是/tmp/serv1。請將此圖與圖15-6對照較。open服務(wù)器第2版在節(jié)中,客戶機(jī)調(diào)用fork和exec構(gòu)造了一個(gè)open服務(wù)器,它說了然如何從子程序向父程序傳達(dá)文件描述符。本節(jié)將開發(fā)一個(gè)精靈進(jìn)度樣式的open服務(wù)器。一個(gè)服務(wù)器辦理所有客戶機(jī)的央求。由于防備使用了fork和exec,我們希望這一設(shè)計(jì)會(huì)更有效的。在客戶機(jī)和服務(wù)器之間仍將使用上一節(jié)說明的三個(gè)函數(shù):serv_listen、serv_accept和cli_conn。這一服務(wù)器將表示:一個(gè)服務(wù)器能夠辦理多個(gè)客戶機(jī),為此使用的技術(shù)是節(jié)中說明的select和poll函數(shù)。本節(jié)所述的客戶機(jī)近似于節(jié)中的客戶機(jī)。確實(shí),文件是完好同樣的(見程序15-12)。在頭文件(見程序15-11)中則加了下面1行:#defineCS_OPEN"/home/stevens/open"/*server'swell-knownname*/由于在這里調(diào)用的是cli_conn而非fork和exec,因此文件與程序15-13完好不同樣。這示于程序15-25中。程序15-25csopen函數(shù)第15章高級進(jìn)度間通信379下載客戶機(jī)與服務(wù)器之間使用的協(xié)議依舊同樣。讓我們先查察服務(wù)器。頭文件(見程序15-26)包括了標(biāo)準(zhǔn)頭文件,并且說了然全局變量和函數(shù)原型。程序15-26頭文件由于此服務(wù)器辦理所有客戶機(jī),因此它必定保存每個(gè)客戶機(jī)連接的狀態(tài)。這是用定義在頭文件中的client數(shù)組實(shí)現(xiàn)的。程序15-27定義了三個(gè)辦理此數(shù)組的函數(shù)。380UNIX環(huán)境高級編程下載程序15-27辦理client數(shù)組的三個(gè)函數(shù)第一次調(diào)用client_add時(shí),它調(diào)用client_alloc、client_alloc又調(diào)用malloc為該數(shù)組的10個(gè)登記項(xiàng)分配空間。在這10個(gè)登記項(xiàng)所實(shí)用完后,再調(diào)用client_add,使realloc分配附加空間。依靠這類動(dòng)向空間分配,我們無需在編譯時(shí)限制client數(shù)組的長度。下載
第15章高級進(jìn)度間通信381若是出錯(cuò),那么由于假定服務(wù)器是精靈進(jìn)度,因此這些函數(shù)調(diào)用log_函數(shù)(見附錄B)。main函數(shù)(見程序15-28)定義全局變量,辦理命令行選擇項(xiàng),爾后調(diào)用loop函數(shù)。若是以-d選擇項(xiàng)調(diào)用服務(wù)器,則它以交互方式運(yùn)行而非精靈進(jìn)度。當(dāng)測試些服務(wù)器時(shí),使用交互運(yùn)行方式。程序15-28main函數(shù)loop函數(shù)是服務(wù)器的無量循環(huán)。我們將給出該函數(shù)的兩種版本。程序15-29是使用select的一種版本。(在4.3+BSD和SVR4之下工作),程序15-30是使用poll(用于SVR4)的另一種版本。程序15-29使用select的loop函數(shù)382UNIX環(huán)境高級編程下載此函數(shù)調(diào)用serv_listen以創(chuàng)辦服務(wù)器關(guān)于客戶機(jī)連接的端點(diǎn)。此函數(shù)的其他部分是一個(gè)循環(huán),它以select調(diào)用開始。在select返回后,兩個(gè)條件可能為真:(1)描述符listenfd可能準(zhǔn)備好讀,這意味著新客戶機(jī)已調(diào)用了cli_conn。為了辦理這類情況。我們將調(diào)用serv_accept,爾后更新client數(shù)組以及與該新客戶機(jī)相關(guān)的簿記信息。(追蹤作為select第一個(gè)參數(shù)的最高描述符編號(hào)。也追蹤使用中的client數(shù)組的最高低標(biāo)。)一個(gè)現(xiàn)存的客戶機(jī)的連接可能準(zhǔn)備好讀。這意味這以下兩事件之一:(a)該客戶機(jī)已經(jīng)停止,或(b)該客戶機(jī)已發(fā)送一新央求。若是read返回0(文件結(jié)束),則可以為一客戶機(jī)停止。若是讀返回值大于0則可判斷有一新央求需辦理,調(diào)用request辦理此新的客戶機(jī)央求。用allset描述符集追蹤當(dāng)前使用的描述符。當(dāng)新客戶機(jī)連至服務(wù)器時(shí),此描述符集的合適位被打開。當(dāng)該客戶機(jī)停止時(shí),合適位就被關(guān)閉。由于客戶機(jī)的所有描述符都
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 食品營養(yǎng)學(xué)食品安全相關(guān)試題及答案解析
- 投資合伙人合作協(xié)議
- 合同之屋頂施工合同
- 2025年自動(dòng)驅(qū)鳥設(shè)備合作協(xié)議書
- 人社部事業(yè)單位聘用合同
- 項(xiàng)目進(jìn)展推進(jìn)記錄
- 電子設(shè)備安裝與維護(hù)合同
- 婚慶策劃活動(dòng)執(zhí)行合同
- 高中英語聽說技能訓(xùn)練:語法篇
- 產(chǎn)品品質(zhì)評價(jià)表格
- 犯罪情報(bào)學(xué)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 2024版《糖尿病健康宣教》課件
- 國家職業(yè)技術(shù)技能標(biāo)準(zhǔn) 5-04-03-01 水產(chǎn)品原料處理工 勞社廳發(fā)200719號(hào)
- 現(xiàn)代家政導(dǎo)論-課件 5.1.2認(rèn)識(shí)家政服務(wù)業(yè)分類
- 公司資產(chǎn)出租管理制度
- 概算審核服務(wù)投標(biāo)方案(技術(shù)方案)
- 《帝國的崩裂:細(xì)說五代十國史》隨筆
- 2025屆陜西省普通高中學(xué)業(yè)水平選擇性考試 政治試卷(含答案 )
- Unit+4+Sports+Getting+Started 高中英語上外版必修第二冊
- 綜合實(shí)踐活動(dòng)小學(xué)-玩紙課件
- 英語閱讀課教案5篇
評論
0/150
提交評論