15unix環(huán)境高級編程_第1頁
15unix環(huán)境高級編程_第2頁
15unix環(huán)境高級編程_第3頁
15unix環(huán)境高級編程_第4頁
15unix環(huán)境高級編程_第5頁
已閱讀5頁,還剩26頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

15unix環(huán)境高級編程15unix環(huán)境高級編程15unix環(huán)境高級編程下載第15章高級進度間通信序言上一章說了然各種UNIX系統(tǒng)供應的IPC經(jīng)典方法,包括:管道、FIFO、信息隊列、信號量和共享儲藏。本章介紹某些高級的IPC以及它們的應用方法,包括:流管道和命紳士管道。使用這些體系,能夠在進度間傳達打開文件描述符。在分別為每一個客戶進度供應一個通道的系統(tǒng)中,這些通信體系使客戶進度能與精靈服務進度會合。4.2BSD和最早供應這些高級形式的IPC,但是到此刻還沒有廣泛使用,也缺少參照文件。本章中很多思想來自Pressotto和Ritchie〔1990〕的論文。流管道流管道是一個雙向(全雙工)管道。單個流管道就能向父、子進度供應雙向的數(shù)據(jù)流。圖15-1顯示了觀察流管道的兩種方式。它與圖14-1的唯一差異是雙向箭頭連線,由于流管道是全雙工的。用戶進度用戶進度或流管通內核圖15-1觀察流管道的兩種方式實例下面用一個流管道再次實現(xiàn)了程序14-9的協(xié)作進度實例。程序15-1是新的main函數(shù)。add2協(xié)作進度與程序14-8中的同樣。程序15-1調用了創(chuàng)辦一個流管道的新函數(shù)s_pipe。(下面將說明該函數(shù)的SVR4和4.3+BSD版本。)程序15-1用流管道驅動add2過濾進度的程序356UNIX環(huán)境高級編程下載父程序只使用fd[0],子程序只使用fd[1]。由于流管道的每一端都是全雙工的,因此父進度讀、寫fd[0],而子程序將fd[1]復制到標準輸入和標準輸出。圖15-2顯示了由此構成的描述符。下載第15章高級進度間通信357s_pipe函數(shù)定義為與標準pipe函數(shù)近似。它的調父進度子進度(協(xié)作進度)用參數(shù)與pipe同樣,但返回的描述符以讀-寫方式打開。實例—SVR4下的s_pipe函數(shù)圖15-2為協(xié)作進度安排的描述符程序15-2是s_pipe函數(shù)的SVR4版本。它可是調用創(chuàng)辦全雙工管道的標準pipe函數(shù)。程序15-2s_pipe函數(shù)的SVR4版本在系統(tǒng)V的早期版本中也能夠創(chuàng)辦流管道,但要進行的辦理很多。相關在下創(chuàng)辦流管道的詳細情況,請參閱Stevens〔1990〕。圖15-3顯示了SVR4之下管道的基本構造。它主若是兩個相互連接的流首。由于管道是一種流設施,故可將辦理模塊壓入管道的任一一端。節(jié)將用此技術供應一個能夠裝置的命名管道。實例—4.3+BSD之下的s_pipe函數(shù)程序15-3是s_pipe函數(shù)的BSD版本。此函數(shù)在4.2BSD及今后的各版本中起作用。它創(chuàng)辦一對互連的UNIX域流套接口。

用戶進度流首流首內核圖15-3SVR4之下的管道自4.2BSD開始,老例的管道已用此方式實現(xiàn)。但是,當調用pipe時,第一個描述符的寫端和第二個描述符的讀端都被關閉。為獲得全雙工管道,必定直接調用socketpair。程序15-3s_pipe函數(shù)的BSD版本358UNIX環(huán)境高級編程下載15.3傳達文件描述符在進度間傳達打開文件描述符的能力特別適用。用此能夠對客戶機/服務器應用進行不同樣的設計。它贊同一個進度(一般是服務器)辦理與打開一個文件相關的所有操作(涉及的細節(jié)可能是:將網(wǎng)絡名翻譯為網(wǎng)絡地址、撥號調制解調器、協(xié)商文件鎖等。)以及向調用進度返回一描述符,該描述符可被用于今后的所有I/O函數(shù)。打開文件或設施的所有細節(jié)對客戶而言都是透明的。4.2BSD支持傳達打開描述符,但其推行中有些錯誤。4.3BSD消除了這些錯誤。及以上版本都支持傳達打開描述符。下面進一步說明“從一個進度向另一個進度傳達一打開文件描述符”的含義。回憶圖3-2,其中顯示了兩個進度,它們打開了同一文件。誠然它們共享同一v節(jié)點表,但每個進度都有它自己的文件表項。當從一個進度向另一個進度傳達一打開文件描述符時,我們想要發(fā)送進度和接收進度共享同一文件表項。圖15-4顯示了所希望的安排。在技術上,發(fā)送進度實質上向接受進度傳達一個指向一打開文件表項的指針。該指針被分配存放在接收進度的第一個可用描述符項中。(注意,不要獲得錯覺以為發(fā)送進度和接收進度中的描述符編號是同樣的,平時它們是不同樣的。)這類情況與在fork此后,父、子進度完好共享一個打開文件表項同樣(見圖8-1)。當發(fā)送進度將描述符傳達給接收進度后,平時它關閉該描述符。發(fā)送進度關閉該描述符其實不造成關閉該文件或設施,其原因是該描述符對應的文件仍需為接收進度打開(即使接收進度還沒有接收到該描述符)。進度表項fd標志ptr文件表文件狀態(tài)標志當前文件位移v節(jié)點表節(jié)點指針v節(jié)點信息進度表項i節(jié)點信息fd標志ptr當前文件長度圖15-4從上一進度傳達一個打開文件至下一進度第15章高級進度間通信359下載下面定義本章使用的三個函數(shù)(第18章也將使用)以發(fā)送和接收文件描述符。本節(jié)將會給出關于SVR4和4.3+BSD的這三個函數(shù)的不同樣實現(xiàn)。#include"ourhdr.h"intsend_fd(intintsend_err(int

spipefd,intspipefd,int

filedes);status,constchar*

errmsg);兩個函數(shù)返回:若成功則為

0,若出錯則為

-1intrecv_fd(int

spipefd,ssize_t(*

userfunc)(int,constvoid*,size_t));返回:若成功則為文件描述符,若出錯則

<0當一個進度(平時是服務器)希望將一個描述符傳達給另一個進度時,它調用send_fd或send_err。等待接收描述符的進度(客戶機)調用recv_fd。send_fd經(jīng)由流管道spipefd發(fā)送描述符filedes。send_err經(jīng)由流管道spipefd發(fā)送errmsg和status字節(jié)。status的值應在-1~-255之間客戶機調用recv_fd接收一描述符。若是所有正常(發(fā)送者調用了send_fd),則作為函數(shù)值返回非負描述符。否則,返回值是由send_err發(fā)送的status(-1~-255之間的一個值)。別的,若是服務器發(fā)送了一條出錯信息,則客戶機調用它自己的userfunc辦理該信息。userfunc的第一個參數(shù)是常數(shù)STDERR_FILENO,爾后是指向出錯信息的指針及其長度??蛻魴C常將userfunc指定為UNIX的write函數(shù)。我們實現(xiàn)了用于這三個函數(shù)的我們自己擬定的協(xié)議。為發(fā)送一描述符,send_fd先發(fā)送兩個0字節(jié),爾后是實質描述符。為了發(fā)送一條出錯信息,send_err發(fā)送errmsg,爾后是1個0字節(jié),最后是status字節(jié)的絕對值(1~255)。recv_fd讀流管道中所有字節(jié)直至null字符。null字符以前的所有字符都送給調用者的userfunc。recv_fd讀到的下一個字節(jié)是status字節(jié)。若status字節(jié)為0,那么一個描述符已傳達,否則表示沒有接收到描述符.send_err函數(shù)在將出錯信息寫到流管道后,即調用send_fd函數(shù)。這示于程序15-4中。程序15-4send_err函數(shù)360UNIX環(huán)境高級編程下載以下三節(jié)介紹了在SVR4、4.3BSD和4.3+BSD下,兩個函數(shù)send_fd和recv_fd的實質實現(xiàn)。SVR4在SVR4之下,文件描述符用兩個ioctl命令在一流管道中交換,這兩個命令是:I_SENDFD和I_RECVFD。為了發(fā)送一描述符,將ioctl的第三個參數(shù)設置為實質描述符。這示于程序15-5中。程序15-5SVR4的send_fd函數(shù)當接收一描述符時,ioctl的第三個參數(shù)是一指向strrecvfd構造的指針。recv_fd讀流管道直到接收到雙字節(jié)協(xié)議的第一個字節(jié)(null字節(jié)).當發(fā)出帶I_RECVFD命令的ioctl時,在流讀首處的第一條信息應當是一個描述符,它是由I_SENDFD發(fā)來的,也許獲得一條出錯信息。這示于程序15-6中。程序15-6SVR4的recv_fd函數(shù)第15章高級進度間通信361下載不幸的是,關于以及在其基礎上構造的SunOS和Ultrix,以及從4.3BSDReno開始的后續(xù)版本必定供應不同樣的實現(xiàn)。為了交換文件描述符,調用sendmsg(2)和recvmsg(2)函數(shù)。這兩個函數(shù)的參數(shù)中都有一個指向msghd的r指針,該構造包括了所相關于要發(fā)送和接收信息的信息。該構造定義在<sys/socket.h>頭文件中,在之下,其樣式是:362UNIX環(huán)境高級編程下載頭兩個元素平時用于在網(wǎng)絡連接上發(fā)送數(shù)據(jù)報文,在這里,目的地址能夠由每個數(shù)據(jù)報文指定。下面兩個元素使我們能夠指定緩存的數(shù)組(散布讀和齊聚寫),這仿佛對readv和writev函數(shù)(見節(jié))的說明同樣。最后兩個元素辦理存取權的傳達和接收。當前獨必然義的存取權是文件描述符。存取權僅可超越一個UNIX域套接口傳送(即在之下作為流管道所使用的)。為了發(fā)送或接收一文件描述符,將msg_accrights設置為指向該整型描述符,將msg_accrightslen設置為描述符的長度(即整型的長度)。僅當此長度非0時,才傳達或接收描述符。程序15-7是4.3BSD的send_fd函數(shù)。程序15-7的send_fd函數(shù)第15章高級進度間通信363下載在sendmsg調用中,發(fā)送雙字節(jié)協(xié)議數(shù)據(jù)(null和status字節(jié))和描述符。為了接收一文件描述符,從流管道讀,直至讀到null字節(jié),它位于最后的status字節(jié)以前。null字節(jié)以前是一條出錯信息,它來自覺送者。這示于程序15-8。程序15-8的recv_fd函數(shù)364UNIX環(huán)境高級編程下載注意,該程序總是準備接收一描述符(在每次調用recvmsg以前,設置msg_accrights和msg_accrightslen),但是僅當在返回時msg_accrightslen非0,才確實接收到一描述符。4.3+BSD從4.3BSDReno開始,更正了msghdr構造的定義。在以前版本中被稱之為“存取權”的最后兩個元素改稱為“輔助數(shù)據(jù)”。別的,在該構造結束處增加了一個新成員msg_flags。此刻,msg_control字段指向一個cmsghdr(控制信息頭)構造。為了發(fā)送一文件描述符,將cmsg_len設置為cmsghdr構造長度加一個整型(描述符)的長度。將cmsg_level設置為SOL_SOCKET,cmsg_type設置為SCM_RIGHTS,這表示正在傳達的是存取權(SCM表示套接口級控制信息)。實質描述符的存放地址緊隨在cmsy_type字段此后,使用CMSG_DATA宏以獲得指向該整型數(shù)的指針。程序15-9示出了4.3BSDReno之下的send_fd函數(shù)。程序15-9的send_fd函數(shù)第15章高級進度間通信365下載為了接收一描述符(見程序15-10),我們?yōu)閏msghdr構造和一描述符分配了足夠的儲藏區(qū),設置

msg_control使其指向所分配到的儲藏區(qū),爾后調用

recvmsg。程序15-104.3BSDReno

recv_fd

函數(shù)366UNIX環(huán)境高級編程下載open服務器第1版當前,使用文件描述符傳達技術開發(fā)了一個open服務器:它是一個可執(zhí)行程序,由一個進度執(zhí)行以打開一個或多個文件。該服務器不是將文件送回調用進度,而是送回一個打開文件描述符。這使該服務器對任何種類的文件(比方調制解調器線或網(wǎng)絡連接)而不只是一般文件都能起作用。這也意味著,用IPC交換最小量的信息—從客戶機到服務器傳達文件名和打開方式,而從服務器到客戶機返回描述符。文件內容則不需用IPC傳達。將服務器設計成一個單獨的可執(zhí)行程序有很多優(yōu)點:任一客戶機都易于和服務器聯(lián)系,這近似于客戶機調用一庫函數(shù)。不需要將一特定服務編碼在應用程序中,而是設計一種可供重用的設施。如若需要更正服務器,那么也只影響一個程序。相反,更新一庫函數(shù)可能要更正調用此庫函數(shù)的所有程序(用連編程序重新連接)。共享庫函數(shù)能夠簡化這類更新。服務器能夠是設置-用戶-ID程序,于是使其擁有客戶機沒有的附加贊同權。注意,一第15章高級進度間通信367下載個庫函數(shù)(或共享庫函數(shù))不能夠供應這類能力。客戶機創(chuàng)辦一流管道,爾后調用fork和exec以調用服務器??蛻魴C經(jīng)流管道發(fā)送央求,服務器經(jīng)管道回送響應。定義客戶機和服務器間的協(xié)議以下:客戶機經(jīng)流管道向服務器發(fā)送以下形式的央求:open<pathname><openmode>0<openmode>是open函數(shù)的第二個參數(shù),以十進制表示。該央求字符串以null字節(jié)結尾。服務器調用send_fd或send_err回送一打開描述符或一條出錯信息。這是一個進度向其父進度發(fā)送一打開描述符的實例。節(jié)將更正此實例,其中使用了一個精靈服務器,它將一個描述符發(fā)送給完好沒關的進度。程序15-11是頭文件,它包括標準系統(tǒng)頭文件,并且定義了各個函數(shù)原型。程序15-11open.h頭文件程序15-12是main函數(shù),其中包括一個循環(huán),它先從標準輸入讀一個路徑名,爾后將該文件復制至標準輸出。它調用函數(shù)csopen以與open服務器聯(lián)系,從其返回一打開描述符。程序15-12main函數(shù)368UNIX環(huán)境高級編程下載程序15-13是函數(shù)csopen,它先創(chuàng)辦一流管道,爾后進行服務器的fork和exec操作。程序15-13csopen函數(shù)子進度關閉管道的一端,父進度關閉另一端。子進度也為它所執(zhí)行的服務器將管道的一端復制到其標準輸入和標準輸出0(另一種可選擇的方案是將描述符fd[1]的ASCII表示形式作為一個參數(shù)傳達給服務器。)父進度將央求發(fā)送給服務器,央求中包括路徑名和打開方式。最后,父進度調用recv_fd以返回描述符或錯誤信息。若是服務器返回一錯誤信息則調用write,向標準出錯輸出該信息。此刻,觀察open服務器。其程序是opend,它由子進度執(zhí)行(見程序15-13)。先觀察第15章高級進度間通信369下載頭文件(見程序15-14),它包括了系統(tǒng)頭文件,并且說了然全局變量和函數(shù)原型。程序15-14頭文件main函數(shù)(見程序15-15)經(jīng)流管道(它的標準輸入)讀來自客戶機的央求,爾后調用函數(shù)request。程序15-15main函數(shù)程序15-16中的request函數(shù)肩負所有工作。它調用函數(shù)buf_args將客戶機央求分解成標準argv型的參數(shù)表,爾后調用函數(shù)cli_args辦理客戶機的參數(shù)。若是所有正常,則調用open打開相應文件,接著調用send_fd,經(jīng)由流管道(它的標準輸出)將描述符回送給客戶機。若是出錯則調用send_err回送一則出錯信息,其中使用了前面說明的客戶機-服務器協(xié)議。客戶機央求是一個空的中斷的字符串,其參數(shù)由空格分開。程序15-17中的buf_args函數(shù)將字符串分解成標準argv型參數(shù)表,并調用用戶函數(shù)辦理參數(shù)。本節(jié)稍后及第18章將用到該函數(shù)。我們使用ANSIC函數(shù)strtok將字符串切割成參數(shù)。程序15-16request函數(shù)370UNIX環(huán)境高級編程下載程序15-17buf_args函數(shù)第15章高級進度間通信371下載buf_args調用的服務器函數(shù)是cli_args(見程序15-18)。它考據(jù)客戶機發(fā)送的參數(shù)可否正確,爾后將路徑名和打開方式存放在全局變量中。這樣也就完成了open服務器,它由客戶機執(zhí)行fork和exec而調用。在fork以前創(chuàng)辦了一個流管道,爾后客戶機和服務器用其進行通信。在這類安排下,每個客戶機都有一服務器。在下一節(jié)觀察了客戶機-服務器連接后,我們將在節(jié)重新實現(xiàn)一個open服務器,其中用一個精靈進度作為服務器,所有客戶機都與其進行聯(lián)系。程序15-18cli_args函數(shù)客戶機-服務器連接函數(shù)關于相關進度(比方,父進度和子進度)之間的IPC,流管道特別適用。前節(jié)所述的open服務器使用未命名的流管道能從子進度向父進度傳達文件描述符。但是當辦理沒關進度時(例如,若服務器是一精靈進度),則需要使用有名的流管道。能夠先構造一未命紳士管道(用s_pipe函數(shù)),爾后對每一端加上一文件系統(tǒng)路徑名。精靈進度服務器將只創(chuàng)辦流管道的一端,并對該端加上一名字。這樣,沒關的客戶機能夠向服務者的流管道端發(fā)送信息,從而與精靈進度匯聚。這近似于圖14-11中所示的情況,在該圖中客戶機使用FIFO發(fā)送它們的央求。一種更好的方法是:服務器創(chuàng)辦一名字公開的流管道的一端,爾后客戶機連接至該端。別的,每次一個新客戶機連至服務器的命紳士管道時,就在客戶機和服務器之間創(chuàng)辦一條嶄新的流管道。這樣,每次一個新客戶機連接至服務器,以及客戶機停止時,服務器都會獲得通知。SVR4和4.3+BSD都支持這類形式的IPC。本節(jié)將開發(fā)三個函數(shù),客戶機-服務器能夠使用這些函數(shù)以建立上述針對每個客戶機的連接。#include"ourhdr.h"intserv_listen(constchar*name);返回:若成功則返回為文件描述符,若出錯則<0372UNIX環(huán)境高級編程下載第一,一個服務器應當宣布,它愿意聽取客戶機在一個盡人皆有名字上的連接,該名字是在文件系統(tǒng)中的一個路徑名。為此調用serv_listen,其參數(shù)name是服務器的盡人皆有名字??蛻魴C希望與服務器連接時使用此名字。該函數(shù)的返回值是命紳士管道服務器端的文件描述符。一旦服務器已調用serv_listen,它將調用serv_accept等待客戶連接到達。#include"ourhdr.h"intserv_accept(intlistenfd,uid_t*uidptr);返回:若成功則返回為文件描述符,若出錯則<0istenfd是serv_listen返回的描述符。在客戶機連接到服務器眾所周知的名字上以前,此函數(shù)其實不返回。當客戶機連接至服務器時,自動創(chuàng)辦一條嶄新的流管道,其新描述符作為該函數(shù)的值返回。別的,客戶機的有功能戶ID經(jīng)過指針uidptr儲藏??蛻魴C為與服務器連接只需調用cli_conn函數(shù)。#include"ourhdr.h"intcli_conn(constchar*

name);返回:若成功則返回為文件描述符,若出錯則

<0客戶指定的name應當與服務器調用serv_listen時宣布的同樣。返回的描述符引用連接至服務器的流管道使用上述三個函數(shù),即可編寫服務器精靈進度,它能夠管理任一數(shù)量的客戶機。唯一的限制是單個進度可用的描述符數(shù),服務器關于每一個客戶機連接都需要一個描述符。由于這些函數(shù)辦理的都是一般文件描述符,因此服務器使用select或poll即可在所有客戶機之間多路轉接I/O央求。最后,由于客戶機-服務器連接都是流管道,因此能夠經(jīng)由連接傳達打開描述符。下面兩節(jié)將說明在SVR4和4.3+BSD之下這三個函數(shù)的實現(xiàn)。第18章開發(fā)一個通用的連接服務器時,也將使用這三個函數(shù)。SVR4SVR4供應裝置的流以及一個名為connld的流辦理模塊,用其能夠供應與服務器有唯一連接的命紳士管道。裝置流和connld模塊是由Presotto和Ritchie[1990]為ResearchUNIX系統(tǒng)開發(fā)的,后出處SVR4采用。用戶進度第一,服務器創(chuàng)辦一未命紳士管道,并將流處理模塊connld壓入一端。圖15-5顯示了這一辦理結果。爾后,使壓入connl的d一端擁有一路徑名。流首流首SVR4供應fattac函h數(shù)實現(xiàn)這一點。任一進度內核(比方客戶機)打開此路徑名就引用該管道的命名端。程序15-19使用了20余行代碼實現(xiàn)serv_listen函數(shù)。圖15-5在一端壓入connld模塊后的流管道下載第15章高級進度間通信373程序15-19SVR4的serv_listen函數(shù)當另一進度對管道的命名端(connld模塊壓入端)調用open時,發(fā)生以下辦理過程:創(chuàng)辦一個新管道。該新管道的一個描述符作為open的返回值回送給客戶機。另一個描述符在命名管道的另一端(亦即不是壓入connld的端)傳達給服務器。服務器以帶I_RECVFD命令的ioctl接受該新描述符。假定服務器用fattach函數(shù)加到其管道的眾所周知的名字是/tmp/serv1。圖15-6顯示了客戶機調用:fd=open("/tmp/serv1",O_RDWR);并返回后產(chǎn)生的結果??蛻魴C服務器流首流首流首流首內核圖15-6客戶機-服務器在命名管道上的連接374UNIX環(huán)境高級編程下載客戶機和服務器之間的管道是open創(chuàng)辦的,被打開的路徑名實際上是一命名管道,其中壓入了connld模塊??蛻魴C獲得由open返回的文件描述符fd。服務器處的新文件描述符是clifdl,它是由服務器在描述符fd[0]上以I_RECVFD命令調用ioctl而接收到的。一旦服務器在fd[1]上壓入了connld模塊,并對fd[1]附接上一個名字,它就不再使用fd[1]。服務器調用程序15-20中的serv_accept函數(shù)等待客戶機連接到達。程序15-20SVR4的serv_accept函數(shù)在圖15-6中,serv_accept的第一個參數(shù)應當是描述符fd[0],serv_accept的返回值是描述符clifdl??蛻魴C調用程序15-21中的cli_conn函數(shù)起動對服務器的連接。程序15-21SVR4的cli_conn函數(shù)我們對返回的描述符可否引用一個流設施進行了兩次檢查,以便辦理服務器沒有起動,但該路徑名卻存在于文件系統(tǒng)中的情況。(在SVR4下,幾乎沒有什么原因去調用cli_conn,而不下載

第15章高級進度間通信375是直接調用open。下一節(jié)將看到,在BSD系統(tǒng)之下,cli_conn函數(shù)要復雜得多,因此編寫cli_conn函數(shù)就很必要。)4.3+BSD在4.3+BSD之下,為了用UNIX域套接口連接客戶機和服務器,需要有一套不同樣的操作函數(shù)。由于應用socket、bind、listen、accept和connect函數(shù)的大多數(shù)細節(jié)與其他網(wǎng)絡協(xié)議相關(拜會Stevens〔1990〕),因此此處不詳細張開。由于SVR4也支持UNIX域套接口,因此本節(jié)所示代碼同樣可在SVR4之下工作。程序15-22包括了serv_listen函數(shù)。它是服務器調用的第一個函數(shù)。程序15-224.3+BSD的serv_listen函數(shù)第一,調用socket函數(shù)創(chuàng)辦一個UNIX域套接口。爾后,填充sockeraddr_un構造,將一個眾所周知的路徑名賦與該套接口。該構造是調用bind函數(shù)的一個參數(shù)。爾后調用listen以通知內核:本服務器正等待來自客戶機的連接。(listen的第二個參數(shù)是5,它是最大的未決連接央求數(shù),376UNIX環(huán)境高級編程下載內核將這些央求對該描述符進行排隊。大多數(shù)實現(xiàn)逼迫該值的上限為5。)客戶機調用cli_conn函數(shù)(見程序15-23)起動與服務器的連接。程序15-234.3+BSD的cli_conn函數(shù)下載第15章高級進度間通信377調用socket函數(shù)以創(chuàng)辦客戶端的UNIX域套接口,爾后客戶機專用的名字填入socketaddr_un構造。該路徑名的最后5個字符是客戶機的進度ID(我們能夠查證此構造的長度是14個字符,以防備UNIX域套接口早期實現(xiàn)的某些錯誤)。在路徑名已經(jīng)存在的情況下調用unlink,爾后再調用bind將一名字賦與客戶機的套接口,這就創(chuàng)辦了文件系統(tǒng)中的路徑名,該文件的種類是套接口。接著調用chmod,它關閉除user_read,user_write和user_execute以外的存取權。在serv_accept中,服務器檢查該套接口的這些贊同權和用戶ID,以考據(jù)用戶的身份。爾后,以服務器眾所周知的路徑名填充另一個socketaddr_un構造。最后,connect函數(shù)起動與服務器的連接。創(chuàng)辦每個客戶機與服務器的唯一連接是經(jīng)過在serv_accept函數(shù)中調用accept函數(shù)實現(xiàn)的(見程序15-24)。程序15-244.3+BSD

的serv_accept函數(shù)378UNIX環(huán)境高級編程下載服務器在調用accept中擁堵以等待客戶機調用客戶機的嶄新的描述符(這近似于SVR4中connld模塊所做的)。別的,accept也經(jīng)過其第二個參數(shù)(指向socketaddr_un構造的指針)返回客戶機賦與其套接口的路徑名(它包括客戶機的進度ID)。用null字節(jié)結束此路徑名,爾后調用stat。這使我們能夠考據(jù)此路徑名確實是一個套接口,其贊同權user_read,user_write和user_execute。我們也考據(jù)與該套接口相關的三

cli_conn。當accept返回時,其返回值是連向客戶機服務器套接口套接口套接口內核圖15-7UNIX域套接口上客戶機-服務器連接個時間不高出30秒。(time函數(shù)返回自UNIX紀元經(jīng)過的時間和日期,它們都以秒計。)若是所有這些檢查都經(jīng)過,則以為該客戶機的身份(其有功能戶ID)是該套接口的所有者。誠然這類檢查其實不完滿,但倒是現(xiàn)有系統(tǒng)所能做得最好的。(若是內核能像SVR4I_RECVFD做的那樣,將有功能戶ID返回給accept,那就更好一些。)圖15-7顯示了cli_conn調用返回后的這類連接,假定服務器眾所周知的名字是/tmp/serv1。請將此圖與圖15-6對照較。open服務器第2版在節(jié)中,客戶機調用fork和exec構造了一個open服務器,它說了然如何從子程序向父程序傳達文件描述符。本節(jié)將開發(fā)一個精靈進度樣式的open服務器。一個服務器辦理所有客戶機的央求。由于防備使用了fork和exec,我們希望這一設計會更有效的。在客戶機和服務器之間仍將使用上一節(jié)說明的三個函數(shù):serv_listen、serv_accept和cli_conn。這一服務器將表示:一個服務器能夠辦理多個客戶機,為此使用的技術是節(jié)中說明的select和poll函數(shù)。本節(jié)所述的客戶機近似于節(jié)中的客戶機。確實,文件是完好同樣的(見程序15-12)。在頭文件(見程序15-11)中則加了下面1行:#defineCS_OPEN"/home/stevens/open"/*server'swell-knownname*/由于在這里調用的是cli_conn而非fork和exec,因此文件與程序15-13完好不同樣。這示于程序15-25中。程序15-25csopen函數(shù)第15章高級進度間通信379下載客戶機與服務器之間使用的協(xié)議依舊同樣。讓我們先查察服務器。頭文件(見程序15-26)包括了標準頭文件,并且說了然全局變量和函數(shù)原型。程序15-26頭文件由于此服務器辦理所有客戶機,因此它必定保存每個客戶機連接的狀態(tài)。這是用定義在頭文件中的client數(shù)組實現(xiàn)的。程序15-27定義了三個辦理此數(shù)組的函數(shù)。380UNIX環(huán)境高級編程下載程序15-27辦理client數(shù)組的三個函數(shù)第一次調用client_add時,它調用client_alloc、client_alloc又調用malloc為該數(shù)組的10個登記項分配空間。在這10個登記項所實用完后,再調用client_add,使realloc分配附加空間。依靠這類動向空間分配,我們無需在編譯時限制client數(shù)組的長度。下載

第15章高級進度間通信381若是出錯,那么由于假定服務器是精靈進度,因此這些函數(shù)調用log_函數(shù)(見附錄B)。main函數(shù)(見程序15-28)定義全局變量,辦理命令行選擇項,爾后調用loop函數(shù)。若是以-d選擇項調用服務器,則它以交互方式運行而非精靈進度。當測試些服務器時,使用交互運行方式。程序15-28main函數(shù)loop函數(shù)是服務器的無量循環(huán)。我們將給出該函數(shù)的兩種版本。程序15-29是使用select的一種版本。(在4.3+BSD和SVR4之下工作),程序15-30是使用poll(用于SVR4)的另一種版本。程序15-29使用select的loop函數(shù)382UNIX環(huán)境高級編程下載此函數(shù)調用serv_listen以創(chuàng)辦服務器關于客戶機連接的端點。此函數(shù)的其他部分是一個循環(huán),它以select調用開始。在select返回后,兩個條件可能為真:(1)描述符listenfd可能準備好讀,這意味著新客戶機已調用了cli_conn。為了辦理這類情況。我們將調用serv_accept,爾后更新client數(shù)組以及與該新客戶機相關的簿記信息。(追蹤作為select第一個參數(shù)的最高描述符編號。也追蹤使用中的client數(shù)組的最高低標。)一個現(xiàn)存的客戶機的連接可能準備好讀。這意味這以下兩事件之一:(a)該客戶機已經(jīng)停止,或(b)該客戶機已發(fā)送一新央求。若是read返回0(文件結束),則可以為一客戶機停止。若是讀返回值大于0則可判斷有一新央求需辦理,調用request辦理此新的客戶機央求。用allset描述符集追蹤當前使用的描述符。當新客戶機連至服務器時,此描述符集的合適位被打開。當該客戶機停止時,合適位就被關閉。由于客戶機的所有描述符都

溫馨提示

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

評論

0/150

提交評論