版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、 下載第15章插口層15.1引言 本書共有三章介紹 Net/3的插口層代碼,本章是第一章。插口概念最早出現(xiàn)于 1983年的4.2BSD版本中,它的主要目的是提供一個(gè)統(tǒng)一的訪問(wèn)網(wǎng)絡(luò)和進(jìn)程間通信協(xié)議的接口。這里討論的Net/3版基于4.3BSD Reno版,該版本與大多數(shù)Unix供應(yīng)商使用的早期的4.2版有些細(xì)小的差別。 如第1.7節(jié)所介紹的,插口層的主要功能是將進(jìn)程發(fā)送的與協(xié)議有關(guān)的請(qǐng)求映射到產(chǎn)生插口時(shí)指定的與協(xié)議有關(guān)的實(shí)現(xiàn)。 為了允許標(biāo)準(zhǔn)的Unix I/O系統(tǒng)調(diào)用,如read和write,也能讀寫網(wǎng)絡(luò)連接,在BSD版本中將文件系統(tǒng)和網(wǎng)絡(luò)功能集成在系統(tǒng)調(diào)用級(jí)。與通過(guò)一個(gè)描述符訪問(wèn)一個(gè)打開的文件一
2、樣, 進(jìn)程也是通過(guò)一個(gè)描述符(一個(gè)小整數(shù))來(lái)訪問(wèn)插口上的網(wǎng)絡(luò)連接。這個(gè)特點(diǎn)使得標(biāo)準(zhǔn)的文件系統(tǒng)調(diào)用, 如read和write,以及與網(wǎng)絡(luò)有關(guān)的系統(tǒng)調(diào)用,如 sendmsg和recvmsg,都能通過(guò)描述符來(lái)處理插口。 我們的重點(diǎn)是插口及相關(guān)的系統(tǒng)調(diào)用的實(shí)現(xiàn)而不是討論如何使用插口層來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)應(yīng)用。關(guān)于進(jìn)程級(jí)的插口接口和如何編寫網(wǎng)絡(luò)應(yīng)用的詳細(xì)討論,請(qǐng)參考 Stevens 1990和Rago 1990。 圖15-1說(shuō)明了進(jìn)程中的插口接口與內(nèi)核中的協(xié)議實(shí)現(xiàn)之間的層次關(guān)系。 應(yīng)用程序 函數(shù)調(diào)用 插口系統(tǒng)調(diào)用系統(tǒng)調(diào)用 進(jìn)程內(nèi)核插口系統(tǒng)調(diào)用實(shí)現(xiàn) 函數(shù)調(diào)用 插口層函數(shù) TP 4 TCP 通過(guò)pr_usrreq或p
3、r_ctloutput調(diào)用 UDP SPP圖15-1 插口層將一般的請(qǐng)求轉(zhuǎn)換為指定的協(xié)議操作 第 15 章 插 口 層349下載splnet處理 插口包含很多對(duì)splnet和splx的成對(duì)調(diào)用。正如第 1.12節(jié)中介紹的,這些調(diào)用保護(hù)訪問(wèn)在插口層和協(xié)議處理層間共享的數(shù)據(jù)結(jié)構(gòu)的代碼。如果不使用 splnet,初始化協(xié)議處理和改變共亨的數(shù)據(jù)結(jié)構(gòu)的軟件中斷將使得插口層代碼恢復(fù)執(zhí)行時(shí)出現(xiàn)混亂。 我們假定讀者理解了這些調(diào)用,因而在以后討論中一般不再特別說(shuō)明它們。 15.2代碼介紹 本章討論涉及的三個(gè)文件在圖 15-2中列出。圖15-2 本章討論涉及的源文件 全局變量本章討論涉及到的兩個(gè)全局變量如圖 15
4、-3所示。圖15-3 本章介紹的全局變量 15.3socket結(jié)構(gòu) 插口代表一條通信鏈路的一端,存儲(chǔ)或指向與鏈路有關(guān)的所有信息。這些信息包括:使用的協(xié)議、協(xié)議的狀態(tài)信息(包括源和目的地址)、到達(dá)的連接隊(duì)列、數(shù)據(jù)緩存和可選標(biāo)志。圖15-5 中給出了插口和與插口相關(guān)的緩存的定義。 4 1 - 4 2so_ type由產(chǎn)生插口的進(jìn)程來(lái)指定,它指明插口和相關(guān)協(xié)議支持的通信語(yǔ)義。so_type的值等于圖7-8所示的pr_type。對(duì)于UDP,so_type等于SOCK_DGRAM,而對(duì)于TCP,so_type則等于SOCK_STREAM。 4 3 so_options是一組改變插口行為的標(biāo)志。圖 15-
5、4列出了這些標(biāo)志。 通過(guò)getsockopt和setsockopt系統(tǒng)調(diào)用進(jìn)程能修改除SO_ACCEPTCONN外所有的插口選項(xiàng)。當(dāng)在插口上發(fā)送listen系統(tǒng)調(diào)用時(shí), SO_ACCEPTCONN被內(nèi)核設(shè)置。 so_ linger等于當(dāng)關(guān)閉一條連接時(shí)插口繼續(xù)發(fā)送數(shù)據(jù)的時(shí)間間隔 (單位為一個(gè)時(shí)鐘滴 4 4答)(第15.15節(jié))。 4 5值。 so_state表示插口的內(nèi)部狀態(tài)和一些其他的特點(diǎn)。圖 15-6列出了so_state可能的取變 量 數(shù)據(jù)類型 描 述 socketps sysentstruct fileops struct syse ntI/O系統(tǒng)調(diào)用的socket實(shí)現(xiàn)系統(tǒng)調(diào)用入口數(shù)組
6、文 件 描 述 sys/socketvar.hsocket結(jié)構(gòu)定義 kern/uipc_syscalls.c kern/uipc_socket.c系統(tǒng)調(diào)用實(shí)現(xiàn)插口層函數(shù) 350TCP/IP詳解 卷2:實(shí)現(xiàn) 下載圖15-4so_options的值圖15-5 struct socke定t義 so_options僅用于內(nèi)核 描 述 SO_ ACCEPTCONN SO_ BROADCAST S O _ D E B U GSO_ DONTROUTE SO_ KEEPAL I VE SO_ OOBI NL I NE SO_ REUSEADDR SO_ REUSEPORTSO_ USELOOPBACK插口接
7、受進(jìn)入的連接插口能夠發(fā)送廣播報(bào)文插口記錄排錯(cuò)信息 輸出操作旁路選路表 插口查詢空閑的連接 插口將帶外數(shù)據(jù)同正常數(shù)據(jù)存放在一起插口能重新使用一個(gè)本地地址 插口能重新使用一個(gè)本地地址和端口 僅針對(duì)選路域插口;發(fā)送進(jìn)程收到它自己的選路請(qǐng)求 第 15 章 插 口 層351下載圖15-5 (續(xù))圖15-6 so_state 的值從圖 1 5 - 6 的第二列中可以看出,進(jìn)程可以通過(guò) f c n t l 和i o c t l 系統(tǒng)調(diào)用直接修改SS_ASYNC和SS_NBIO。對(duì)于其他的標(biāo)志,進(jìn)程只能在系統(tǒng)調(diào)用的執(zhí)行過(guò)程中間接修改。例如,如果進(jìn)程調(diào)用connect,當(dāng)連接被建立時(shí), SS_ISCONNECT
8、ED標(biāo)志就會(huì)被內(nèi)核設(shè)置。 SS_NBIO和SS_ASYNC標(biāo)志 在默認(rèn)情況下,進(jìn)程在發(fā)出I/O請(qǐng)求后會(huì)等待資源。例如,對(duì)一個(gè)插口發(fā) read系統(tǒng)調(diào)用, 如果當(dāng)前沒(méi)有網(wǎng)絡(luò)上來(lái)的數(shù)據(jù),則 read系統(tǒng)調(diào)用就會(huì)被阻塞。同樣,當(dāng)一個(gè)進(jìn)程調(diào)用 write 系統(tǒng)調(diào)用時(shí),如果內(nèi)核中沒(méi)有緩存來(lái)存儲(chǔ)發(fā)送的數(shù)據(jù),則內(nèi)核將阻塞進(jìn)程。如果設(shè)置了SS_NBIO,在對(duì)插口執(zhí)行I/O操作且請(qǐng)求的資源不能得到時(shí),內(nèi)核并不阻塞進(jìn)程,而是返回EWOULDBLOCK。 如果設(shè)置了 S S _ A S Y N C,當(dāng)因?yàn)橄铝星闆r之一而使插口狀態(tài)發(fā)生變化時(shí),內(nèi)核發(fā)送 SIGIO信號(hào)給so_pgid標(biāo)識(shí)的進(jìn)程或進(jìn)程組: 連接請(qǐng)求已完成;
9、 斷連請(qǐng)求已被啟動(dòng); 斷連請(qǐng)求已完成; 連接的一個(gè)通道已被關(guān)閉; 插口上有數(shù)據(jù)到達(dá); 數(shù)據(jù)已被發(fā)送(即,輸出緩存中有閑置空間);或 UDP或TCP插口上出現(xiàn)了一個(gè)異步差錯(cuò)。 4 6 so_pcb指向協(xié)議控制塊,協(xié)議控制塊包含與協(xié)議有關(guān)的狀態(tài)信息和插口參數(shù)。每一種協(xié)議都定義了自己的控制塊結(jié)構(gòu),所以 so_pcb被定義成一個(gè)通用的指針。圖 15-7列出了我們討論的控制塊結(jié)構(gòu)。 so_pcb從來(lái)不直接指向tcpcb結(jié)構(gòu);參考圖22-1。 so_state僅用于內(nèi)核 描 述 S S _ A S Y NC S S _ NB I O插口應(yīng)該I/O的異步插口操作不能阻塞進(jìn)程 S S _ CANT RCVMO
10、RE S S _ CANT SENDMORE S S _ I S CONF I RM I NG S S _ I S CONNECT ED S S _ I S CONNECT I NGSS_ I SDI SCONNECT I NG S S _ NO FD REFS S _ P R I VS S _ R C V A T M A R K插口不能再?gòu)膶?duì)方接收數(shù)據(jù)插口不能再發(fā)送數(shù)據(jù)給對(duì)方插口正在協(xié)商一個(gè)連接請(qǐng)求插口被連接到外部插口 插口正在連接一個(gè)外部插口插口正在同對(duì)方斷連 插口沒(méi)有同任何描述符相連 插口由擁有超級(jí)用戶權(quán)限的進(jìn)程所產(chǎn)生 在最近的帶外數(shù)據(jù)到達(dá)之前,插口已處理完所有收到的數(shù)據(jù) 352TCP/
11、IP詳解 卷2:實(shí)現(xiàn) 圖15-7 協(xié)議控制塊 4 7 so_proto指向進(jìn)程在socket系統(tǒng)調(diào)用(第7.4節(jié))中選擇的協(xié)議的protosw結(jié)構(gòu)。 4 8 - 6 4設(shè)置了SO_ACCEPTCONN標(biāo)志的插口維護(hù)兩個(gè)連接隊(duì)列。還沒(méi)有完全建立的連接 (如TCP的三次握手還沒(méi)完成 )被放在隊(duì)列so_ q0中。已經(jīng)建立的連接或?qū)⒈唤邮艿倪B接 (例如, TCP的三次握手已完成)被放入隊(duì)列so_q中。隊(duì)列的長(zhǎng)度分別為 so_q0len和so_qlen。每一個(gè)被排隊(duì)的連接由它自己的插口來(lái)表示。在每一個(gè)被排隊(duì)的插口中, so_head指向設(shè)置了SO_ACCEPTCONN的源插口。 插口上可排隊(duì)的連接數(shù)通過(guò)
12、 so_qlimit來(lái)控制,進(jìn)程可以通過(guò)listen系統(tǒng)調(diào)用來(lái)設(shè)置so_qlimit。內(nèi)核隱含設(shè)置的上限為 5 ( SOMAXCONN,圖15-24)和下限為0。圖15-29中顯示的有點(diǎn)晦澀的公式使用so_qlimit來(lái)控制排隊(duì)的連接數(shù)。 圖15-8說(shuō)明了有三個(gè)連接將被接受、一個(gè)連接已被建立的情況下的隊(duì)列內(nèi)容。 圖15-8 插口連接隊(duì)列 6 5so_timeo用作accept、connet和close處理期間的等待通道(wait channel,第15.10節(jié))。6 6 so_error保存差錯(cuò)代碼,直到在引用該插口的下一個(gè)系統(tǒng)調(diào)用期間差錯(cuò)代碼能送給進(jìn)程。 6 7 如果插口的SS_ASYNC被
13、設(shè)置,則SIGIO信號(hào)被發(fā)送給進(jìn)程(如果so_pgid大于0)或進(jìn)程組( 如果so_pgid 小于0) ??梢酝ㄟ^(guò)ioctl 的SIOCSPGRP 和SIOCGPGRP 命令來(lái)修改或檢查so_pgid的值。關(guān)于進(jìn)程組的更詳細(xì)信息請(qǐng)參考Stevens 1992。 6 8so_oobmark標(biāo)識(shí)在輸入數(shù)據(jù)流中最近收到的帶外數(shù)據(jù)的開始點(diǎn)。第 16.11節(jié)將討論插口 對(duì)帶外數(shù)據(jù)的支持,第29.7節(jié)將討論TCP中的帶外數(shù)據(jù)的語(yǔ)義。 當(dāng)TCP SYN被應(yīng)答時(shí)將插口移入此隊(duì)列, accept將插口從此隊(duì)列中刪除 當(dāng)TCP SYN 到達(dá)時(shí),插口進(jìn)入此隊(duì)列 協(xié) 議 控 制 塊 參考章節(jié) UDPstruct in
14、pcb第22.3節(jié) TCPstruct inpcb struct tcpcb第22.3節(jié)第24.5節(jié) ICMP、IGMP和原始IPstruct inpcb第22.3節(jié) 路由 struct rawcb第20.3節(jié) 下載 第 15 章 插 口 層353下載6 9 - 8 2 每一個(gè)插口包括兩個(gè)數(shù)據(jù)緩存, so_rcv和so_snd,分別用來(lái)緩存接收或發(fā)送的數(shù)據(jù)。so_rcv和so_snd是包含在插口結(jié)構(gòu)中的結(jié)構(gòu)而不是指向結(jié)構(gòu)的指針。我們將在第 16章中描述插口緩存的結(jié)構(gòu)和使用。 8 3 - 8 6 在Net/3中不使用so_tpcb。so_upcall和so_upcallarg也僅用于Net/3中
15、的NFS軟件。 NFS與通常的軟件不太一樣。在很大程度上它是一個(gè)進(jìn)程級(jí)的應(yīng)用但卻在內(nèi)核中運(yùn)行。當(dāng)數(shù)據(jù)到達(dá)接收緩存時(shí),通過(guò) so_upcall來(lái)觸發(fā)NFS的輸入處理。在這種情況下, tsleep和wakeup機(jī)制是不合適的,因?yàn)镹FS協(xié)議是在內(nèi)核中運(yùn)行而不是作為一個(gè)普通進(jìn)程。 文件socketvar.h和uipc_socket2.c定義了幾個(gè)簡(jiǎn)化插口層代碼的宏和函數(shù)。圖15-9對(duì)它們進(jìn)行了描述。 圖15-9 插口的宏和函數(shù) 名 稱 描 述 sosendallatonces o中指定的協(xié)議要求每一個(gè)發(fā)送系統(tǒng)調(diào)用產(chǎn)生一個(gè)協(xié)議請(qǐng)求嗎? int sosendallatonce(struct socket
16、 so*);soisconnecting將插口狀態(tài)設(shè)置為SO_ISCONNECTINGint soisconnecting(struct socket so*);soisconnected參考圖15-30soreadable插口so上的讀調(diào)用不阻塞就返回信息嗎? int soreadable(struct socket so*);sowriteable插口so上的寫調(diào)用不阻塞就返回嗎? int sowriteable(struct socket so*);socantsendmore設(shè)置插口標(biāo)志SO_CANTSENDMORE。喚醒所有等待在發(fā)送緩存上的進(jìn)程 int socantsendmore
17、(struct socket so*);socantrcvmore設(shè)置插口標(biāo)志SO_CANTRCVMORE。喚醒所有等待在接收緩存上的進(jìn)程 int socantrcvmore(struct socket so*);soisdisconnecting清除SS_ISCONNECTING標(biāo)志。設(shè)置SS_ISDISCONG、SS_CANTRCVMORE和SS_CANTSENDMORE標(biāo)志。喚醒所有等待在插口上的進(jìn)程 int soisdisconnecting(struct socket so*);soisdisconnected清除SS_ISCONNECTING、SS_ISCONNECTED和SS_I
18、SDISCONNECTING標(biāo)志。設(shè)置SS_CANTRCVMORE和SS_CANTSENDMORE標(biāo)志。喚醒所有等待在插 口上的進(jìn)程或等待close完成的進(jìn)程 int soisdisconnected(struct socket so*);soqinsque將so插入head指向的隊(duì)列中。如果q等于0,插口到存放未完成的連接的so_q0隊(duì)列的后面。否則,插口到存放準(zhǔn)備接受的連接的隊(duì)列so_q的后面。Net/1錯(cuò)誤地將插口插到隊(duì)列的前面 int soqinsque(struct socket * head, struct socket * so, int q);soqremque從隊(duì)列q中刪除s
19、o。通過(guò)so-so_head來(lái)定位插口隊(duì)列 int soqremque(struct socket so*, int q); 354TCP/IP詳解 卷2:實(shí)現(xiàn) 下載15.4系統(tǒng)調(diào)用 進(jìn)程同內(nèi)核交互是通過(guò)一組定義好的函數(shù)來(lái)進(jìn)行的,這些函數(shù)稱為系統(tǒng)調(diào)用。在討論支持網(wǎng)絡(luò)的系統(tǒng)調(diào)用之前,我們先來(lái)看看系統(tǒng)調(diào)用機(jī)制的本身。 從進(jìn)程到內(nèi)核中的受保護(hù)的環(huán)境的轉(zhuǎn)換是與機(jī)器和實(shí)現(xiàn)相關(guān)的。在下面的討論中,我們使用Net/3在386上的實(shí)現(xiàn)來(lái)說(shuō)明如何實(shí)現(xiàn)有關(guān)的操作。 在BSD內(nèi)核中,每一個(gè)系統(tǒng)調(diào)用均被編號(hào),當(dāng)進(jìn)程執(zhí)行一個(gè)系統(tǒng)調(diào)用時(shí),硬件被配置成僅傳送控制給一個(gè)內(nèi)核函數(shù)。將標(biāo)識(shí)系統(tǒng)調(diào)用的整數(shù)作為參數(shù)傳給該內(nèi)核函數(shù)。在
20、 386實(shí)現(xiàn)中, 這個(gè)內(nèi)核函數(shù)為syscall。利用系統(tǒng)調(diào)用的編號(hào), syscall在表中找到請(qǐng)求的系統(tǒng)調(diào)用的sysent結(jié)構(gòu)。表中的每一個(gè)單元均為一個(gè)sysent結(jié)構(gòu)。 struct sysent int sy_narg;/* number of arguments */int (*sy_call) (); /* implementing function */* system call table entry */;表中有幾個(gè)項(xiàng)是從sysent數(shù)組中來(lái)的,該數(shù)組是在kern/init_sysent.c中定義的。 struct sysent sysent = /* . . . */ 3, r
21、ecvmsg , 3, sendmsg , 6, recvfrom ,3, accept ,3, getpeername ,3, getsockname ,/* . . . */* 27 = recvmsg */* 28 = sendmsg */* 29 = recvfrom */* 30 = accept */* 31=getpeername */* 32 = getsockname */例如, recvmsg系統(tǒng)調(diào)用在系統(tǒng)調(diào)用表中的第 27個(gè)項(xiàng),它有兩個(gè)參數(shù),利用內(nèi)核中的 recvmsg函數(shù)實(shí)現(xiàn)。 syscall將參數(shù)從調(diào)用進(jìn)程復(fù)制到內(nèi)核中,并且分配一個(gè)數(shù)組來(lái)保存系統(tǒng)調(diào)用的結(jié)果。然后,當(dāng)系
22、統(tǒng)調(diào)用執(zhí)行完成后, syscall將結(jié)果返回給進(jìn)程。syscall將控制交給與系統(tǒng)調(diào)用相對(duì)應(yīng)的內(nèi)核函數(shù)。在386實(shí)現(xiàn)中,調(diào)用有點(diǎn)像: struct sysent *callp;error = (*callp-sy_call) (p, args, rval);這里指針callp指向相關(guān)的sysent結(jié)構(gòu);指針p則指向調(diào)用系統(tǒng)調(diào)用的進(jìn)程的進(jìn)程表項(xiàng); args 作為參數(shù)傳給系統(tǒng)調(diào)用,它是一個(gè) 32 bit長(zhǎng)的字?jǐn)?shù)組;而rval則是一個(gè)用來(lái)保存系統(tǒng)調(diào)用的返回結(jié)果的數(shù)組,數(shù)組有兩個(gè)元素,每個(gè)元素是一個(gè) 32 bit長(zhǎng)的字。當(dāng)我們用 “系統(tǒng)調(diào)用” 這個(gè)詞時(shí),我們指的是被syscall調(diào)用的內(nèi)核中的函數(shù),而
23、不是應(yīng)用調(diào)用的進(jìn)程中的函數(shù)。 syscall期望系統(tǒng)調(diào)用函數(shù)(即sy_call指向的函數(shù))在沒(méi)有差錯(cuò)時(shí)返回 0,否則返回非0 的差錯(cuò)代碼。如果沒(méi)有差錯(cuò)出現(xiàn),內(nèi)核將 rval中的值作為系統(tǒng)調(diào)用(應(yīng)用調(diào)用的)的返回值傳送給進(jìn)程。如果有差錯(cuò), syscall忽略rval中的值,并以與機(jī)器相關(guān)的方式返回差錯(cuò)代碼給進(jìn)程,使得進(jìn)程能從外部變量 errno中得到差錯(cuò)代碼。應(yīng)用調(diào)用的函數(shù)則返回 -1或一個(gè)空指針表示應(yīng)用應(yīng)該查看errno獲得差錯(cuò)信息。 在386上的實(shí)現(xiàn),設(shè)置進(jìn)位比特(carry bit) 來(lái)表示syscall的返回值是一個(gè)差錯(cuò)代碼。進(jìn)程中的系統(tǒng)調(diào)用殘樁將差錯(cuò)代碼賦給 errno,并返回- 1或
24、空指針給應(yīng)用。如果沒(méi)有設(shè)置進(jìn)位 第 15 章 插 口 層355下載比特,則將syscall返回的值返回給進(jìn)程中的系統(tǒng)調(diào)用的殘樁。 總之,實(shí)現(xiàn)系統(tǒng)調(diào)用的函數(shù)“返回”兩個(gè)值:一個(gè)給 syscall函數(shù);在沒(méi)有差錯(cuò)的情況下,syscall將另一個(gè)(在rval中)返回給調(diào)用進(jìn)程。 15.4.1 舉 例 socket系統(tǒng)調(diào)用的原型是: int socket(int domain, int type, int protocol);實(shí)現(xiàn)socket系統(tǒng)調(diào)用的內(nèi)核函數(shù)的原型是: struct socket_args int domain; int type;int protocol;socket(struct
25、 proc *p, struct socket_args *uap, int *retval);當(dāng)一個(gè)應(yīng)用調(diào)用socket時(shí),進(jìn)程用系統(tǒng)調(diào)用機(jī)制將三個(gè)獨(dú)立的整數(shù)傳給內(nèi)核。 syscall 將參數(shù)復(fù)制到32bit值的數(shù)組中,并將數(shù)組指針作為第二個(gè)參數(shù)傳給 socket的內(nèi)核版。內(nèi)核版的socket將第二個(gè)參數(shù)作為指向socket_args結(jié)構(gòu)的指針。圖15-10顯示了上述過(guò)程。 進(jìn)程 內(nèi)核圖15-10 socket 參數(shù)處理同socket類似,每一個(gè)實(shí)現(xiàn)系統(tǒng)調(diào)用的內(nèi)核函數(shù)將 args說(shuō)明成一個(gè)與系統(tǒng)調(diào)用有關(guān)的結(jié)構(gòu)指針,而不是一個(gè)指向32 bit的字的數(shù)組的指針。 當(dāng)原型無(wú)效時(shí),隱式的類型轉(zhuǎn)換僅在
26、傳統(tǒng)的 K&R C中或ANSI C中是合法的。如果原型是有效的,則編譯器將產(chǎn)生一個(gè)警告。 syscall在執(zhí)行內(nèi)核系統(tǒng)調(diào)用函數(shù)之前將返回值置為 0。如果沒(méi)有差錯(cuò)出現(xiàn),系統(tǒng)調(diào)用函數(shù)直接返回而不需清除 *retval,syscall返回0給進(jìn)程。 15.4.2 系統(tǒng)調(diào)用小結(jié) 圖15-11對(duì)與網(wǎng)絡(luò)有關(guān)的系統(tǒng)調(diào)用進(jìn)行了小結(jié)。 我們將在本章中討論建立、服務(wù)器、客戶和終止類系統(tǒng)調(diào)用。輸入、輸出類系統(tǒng)調(diào)用將在第16章中介紹,管理類系統(tǒng)調(diào)用將在第 17章中介紹。 從用戶空間復(fù)制到內(nèi)核空間的參數(shù) 356TCP/IP詳解 卷2:實(shí)現(xiàn) 下載圖15-11 Net/3中的網(wǎng)絡(luò)系統(tǒng)調(diào)用 圖15-12 網(wǎng)絡(luò)系統(tǒng)調(diào)用流程圖
27、類 別 名 稱 功 能 建 立 socket bind在指明的通信域內(nèi)產(chǎn)生一個(gè)未命名的插口分配一個(gè)本地地址給插口 服務(wù)器 listen accept使插口準(zhǔn)備接收連接請(qǐng)求等待并接受連接 客 戶 connect同外部插口建立連接 輸 入 read readv recv recvfrom recvmsg接收數(shù)據(jù)到一個(gè)緩存中接收數(shù)據(jù)到多個(gè)緩存中指明選項(xiàng)接收數(shù)據(jù) 接收數(shù)據(jù)和發(fā)送者的地址 接收數(shù)據(jù)到多個(gè)緩存中,接收控制信息和發(fā)送者地址;指明接收選項(xiàng) 輸 出 write writev send sendto sendmsg發(fā)送一個(gè)緩存中的數(shù)據(jù)發(fā)送多個(gè)緩存中的數(shù)據(jù)指明選項(xiàng)發(fā)送數(shù)據(jù) 發(fā)送數(shù)據(jù)到指明的地址 從多
28、個(gè)緩存發(fā)送數(shù)據(jù)和控制信息到指明的地址;指明發(fā)送選項(xiàng) I/Oselect等待I/O 終 止 shutdown close終止一個(gè)或兩個(gè)方向上的連接終止連接并釋放插口 管 理 fcntl ioctl setsockopt getsockopt getsockname getpeername修改I/O語(yǔ)義 各類插口操作 設(shè)置插口或協(xié)議選項(xiàng)得到插口或協(xié)議選項(xiàng) 得到分配給插口的本地地址得到分配給插口的遠(yuǎn)端地址 第 15 章 插 口 層357下載圖15-12畫出了應(yīng)用使用這些系統(tǒng)調(diào)用的順序。大方塊中的 I/O系統(tǒng)調(diào)用可以在任何時(shí)候調(diào)用。該圖不是一個(gè)完整的狀態(tài)流程圖,因?yàn)橐恍┱_的轉(zhuǎn)換在本圖中沒(méi)有畫出;僅顯
29、示了一些常見(jiàn)的轉(zhuǎn)換。 15.5進(jìn)程、描述符和插口 在描述插口系統(tǒng)調(diào)用之前,我們需要介紹將進(jìn)程、描述符和插口聯(lián)系在一起的數(shù)據(jù)結(jié)構(gòu)。圖15-13給出了這些結(jié)構(gòu)以及與我們的討論有關(guān)的結(jié)構(gòu)成員。關(guān)于文件結(jié)構(gòu)的更復(fù)雜的解釋請(qǐng)參考Leffer ea al. 1989。 圖15-13 進(jìn)程、文件和插口結(jié)構(gòu) 實(shí)現(xiàn)系統(tǒng)調(diào)用的函數(shù)的第一個(gè)參數(shù)總為p,即指向調(diào)用進(jìn)程的proc結(jié)構(gòu)的指針。內(nèi)核利用proc結(jié)構(gòu)記錄進(jìn)程的有關(guān)信息。在 proc結(jié)構(gòu)中, p_fd指向filedesc結(jié)構(gòu),該結(jié)構(gòu)的主要功能是管理fd_ofiles指向的描述符表。描述符表的大小是動(dòng)態(tài)變化的,由一個(gè)指向 file結(jié)構(gòu)的指針數(shù)組組成。每一個(gè)fil
30、e結(jié)構(gòu)描述一個(gè)打開的文件,該結(jié)構(gòu)可被多個(gè)進(jìn)程共亨。 圖15-13僅顯示了一個(gè)file結(jié)構(gòu)。通過(guò)p-p_fd-fd_ofilesfd訪問(wèn)到該結(jié)構(gòu)。在file結(jié)構(gòu)中,有兩個(gè)結(jié)構(gòu)成員是我們感興趣的: f_ops和f_data。I/O系統(tǒng)調(diào)用(如read和write)的實(shí)現(xiàn)因描述符中的I/O對(duì)象類型的不同而不同。 f_ops指向fileops結(jié)構(gòu),該結(jié)構(gòu)包含一張實(shí)現(xiàn)read、write、ioctl、select和close系統(tǒng)調(diào)用的函數(shù)指針表。圖 15-13 顯示f_ops指向一個(gè)全局的fileops結(jié)構(gòu),即socketops,該結(jié)構(gòu)包含指向插口用的函數(shù)的指針。 f_ data指向相關(guān)I/ O對(duì)象的專
31、用數(shù)據(jù)。對(duì)于插口而言, f_ data指向與描述符相關(guān)的socket結(jié)構(gòu)。最后, socket結(jié)構(gòu)中的so_proto指向產(chǎn)生插口時(shí)選中的協(xié)議的protosw結(jié)構(gòu)?;叵胍幌?,每一個(gè)protosw結(jié)構(gòu)是由與該協(xié)議關(guān)聯(lián)的所有插口共亨的。 下面我們開始討論系統(tǒng)調(diào)用。 358TCP/IP詳解 卷2:實(shí)現(xiàn) 下載15.6socket系統(tǒng)調(diào)用 s o c k e t系統(tǒng)調(diào)用產(chǎn)生一個(gè)新的插口,并將插口同進(jìn)程在參數(shù)d o m a i n 、t y p e 和protocol中指定的協(xié)議聯(lián)系起來(lái)。該函數(shù) (如圖15-14所示)分配一個(gè)新的描述符,用來(lái)在后續(xù)的系統(tǒng)調(diào)用中標(biāo)識(shí)插口,并將描述符返回給進(jìn)程。 圖15-14
32、 socket 系統(tǒng)調(diào)用4 2 - 55在每一個(gè)系統(tǒng)調(diào)用的前面,都定義了一個(gè)描述進(jìn)程傳遞給內(nèi)核的參數(shù)的結(jié)構(gòu)。在這 種情況下,參數(shù)是通過(guò)socket_args傳入的。所有插口層系統(tǒng)調(diào)用都有三個(gè)參數(shù): p,指向調(diào)用進(jìn)程的proc結(jié)構(gòu); uap,指向包含進(jìn)程傳送給系統(tǒng)調(diào)用的參數(shù)的結(jié)構(gòu); retval,用來(lái)接收系統(tǒng)調(diào)用的返回值。在通常情況下,忽略參數(shù) p和retval,引用uap所指的結(jié)構(gòu)中的內(nèi)容。 5 6 - 60falloc分配一個(gè)新的file結(jié)構(gòu)和fd_ofiles數(shù)組(圖15-13)中的一個(gè)元素。fp指 向新分配的結(jié)構(gòu), fd則為結(jié)構(gòu)在數(shù)組 fd_ ofiles中的索引。socket將file
33、結(jié)構(gòu)設(shè)置成可讀、可寫,并且作為一個(gè)插口。將所有插口共亨的全局 f i l e o ps結(jié)構(gòu)so c k et o p s 連接到f_ops指向的file結(jié)構(gòu)中。socketops變量在編譯時(shí)被初始化,如圖15-15所示。 成 員 值 6 0 - 6 9socreate分配并初始化一個(gè) socket結(jié)構(gòu)。如果 圖15-15 socketops :插口用全局fileops 結(jié)構(gòu) socreate執(zhí)行失敗,將差錯(cuò)代碼賦給 error,釋放file結(jié) 第 15 章 插 口 層359下載構(gòu),清除存放描述符的數(shù)組元素。如果 socreate執(zhí)行成功,將f_data指向socket結(jié)構(gòu), 建立插口和描述符之
34、間的聯(lián)系。通過(guò) *retval將fd返回給進(jìn)程。 socket返回0或返回由socreate返回的差錯(cuò)代碼。 15.6.1 socreate函數(shù) 大多數(shù)插口系統(tǒng)調(diào)用至少被分成兩個(gè)函數(shù),與 socket和socreate類似。第一個(gè)函數(shù)從進(jìn)程那里獲取需要的數(shù)據(jù),調(diào)用第二個(gè)函數(shù) soxxx來(lái)完成功能處理,然后返回結(jié)果給進(jìn)程。這 種分成多個(gè)函數(shù)的做法是為了第二個(gè)函數(shù)能直接被基于內(nèi)核的網(wǎng)絡(luò)協(xié)議調(diào)用,如 socreate的代碼如圖15-16所示。 NFS 。圖15-16 socreate 函數(shù)4 3 - 5 2 socreate共有四個(gè)參數(shù): dom,請(qǐng)求的協(xié)議域(如,PF_INET);aso,保存指向
35、一個(gè)新的socket結(jié)構(gòu)的指針; type,請(qǐng)求的插口類型(如,SOCK_STREAM);proto,請(qǐng)求的協(xié)議。 1. 發(fā)現(xiàn)協(xié)議交換表 360TCP/IP詳解 卷2:實(shí)現(xiàn) 下載5 3 - 6 0如果proto等于非0值, pffindproto查找進(jìn)程請(qǐng)求的協(xié)議。如果 proto等于0, pffindtype用由type指定的語(yǔ)義在指定域中查找一種協(xié)議。這兩個(gè)函數(shù)均返回一個(gè)指向匹配協(xié)議的protosw結(jié)構(gòu)的指針或空指針(參考第7.6節(jié))。 2. 分配并初始化socket結(jié)構(gòu) 6 1 - 6 6socreate分配一個(gè)新的socket結(jié)構(gòu),并將結(jié)構(gòu)內(nèi)容全清成0,記錄下type。如果調(diào)用進(jìn)程有超
36、級(jí)用戶權(quán)限,則設(shè)置插口結(jié)構(gòu)中的 SS_PRIV標(biāo)志。 3. PRU_ATTACH請(qǐng)求 6 7 - 6 9在與協(xié)議無(wú)關(guān)的插口層中發(fā)送與協(xié)議有關(guān)的請(qǐng)求的第一個(gè)例子出現(xiàn)在 socreate中。 回想在第7.4節(jié)和圖15-13中,so-so_proto-pr_usrreq是一個(gè)指向與插口so相關(guān)聯(lián)的協(xié)議的用戶請(qǐng)求函數(shù)指針。每一個(gè)協(xié)議均提供了一個(gè)這樣的函數(shù)來(lái)處理從插口層來(lái)的通信請(qǐng)求。函數(shù)原型是: int pr_usrreq(struct socket *so, int req, struct mbuf *mo, *m1, *m2);第一個(gè)參數(shù)是一個(gè)指向相關(guān)插口的指針, req是一個(gè)標(biāo)識(shí)請(qǐng)求的常數(shù)。后三個(gè)
37、參數(shù) (m0, m1,m2)因請(qǐng)求不同而異。它們總是被作為一個(gè)mbuf結(jié)構(gòu)指針傳遞,即使它們是其他的類型。在必要的時(shí)候,進(jìn)行類似轉(zhuǎn)換以避免編譯器的警告。 圖15-17列出了pr_usrreq函數(shù)提供的通信請(qǐng)求。每一個(gè)請(qǐng)求的語(yǔ)義起決于服務(wù)請(qǐng)求的協(xié)議。 圖15-17 pr_usrreq 函數(shù)PRU_ CONNECT 2請(qǐng)求只用于 Unix域,它的功能是將兩個(gè)本地插口連接起來(lái)。Unix的管道(pipe)就是通過(guò)這種方式來(lái)實(shí)現(xiàn)的。 4. 退出處理 7 0 - 77回到socreate,函數(shù)將協(xié)議交換表連接到插口,發(fā)送 PRU_ATTACH請(qǐng)求協(xié)議 請(qǐng) 求 參 數(shù) 描 述 m0m1m2PRU _ ABO
38、R T PRU_ ACCEPT PRU_ ATTACH PRU _ B I NDPRU_ CONNECT PRU_ CONNECT 2 PRU _ DET ACHPRU_ D I S CONNECT PR U _ L I S T ENPRU_ PEERADDR PRU _ RCVDPRU_ RCVOOB PRU _ S ENDPRU_ S ENDOOB PRU_ SHUTDOWN PRU_ SOCKADDRbuffer data dataaddress protocol address address socket2buffer flags flags address addressbuffe
39、rcontrol control異常終止每一個(gè)存在的連接等待并接受連接 產(chǎn)生了一個(gè)新的插口綁定地址到插口 同地址建立關(guān)聯(lián)或連接將兩個(gè)插口連在一起 插口被關(guān)閉 切斷插口和另一地址間的關(guān)聯(lián)開始連接請(qǐng)求 返回與插口關(guān)聯(lián)的對(duì)方地址進(jìn)程已收到一些數(shù)據(jù) 接收OOB數(shù)據(jù)發(fā)送正常數(shù)據(jù)發(fā)送OOB數(shù)據(jù) 結(jié)束同另一地址的通信 返回與插口相關(guān)聯(lián)的本地地址 第 15 章 插 口 層361下載已建立一個(gè)新的連接端點(diǎn)。該請(qǐng)求引起大多數(shù)協(xié)議,如 TCP和UDP,分配并初始化所有支持 新的連接端點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。 15.6.2 超級(jí)用戶 圖15-18列出了要求超級(jí)用戶權(quán)限的網(wǎng)絡(luò)操作。 圖15-18 Net/3中的超級(jí)用戶 當(dāng)多播i
40、 o c t l命令( S I O C A D D M U L T I 和S I O C D E L M U L T I )是被I P _ A D D _ MEMBERSHIP和IP_DROP_MEMBERSHIP插口選項(xiàng)間接激活時(shí),它可以被非超級(jí)用戶訪問(wèn)。 在圖15-18中,“進(jìn)程”欄表示請(qǐng)求必須由超級(jí)用戶進(jìn)程來(lái)發(fā)起,“插口”欄表示請(qǐng)求必須是針對(duì)由超級(jí)用戶產(chǎn)生的插口 (也就是說(shuō),進(jìn)程不需要超級(jí)用戶權(quán)限,而只需有訪問(wèn)插口的權(quán)限,習(xí)題 1 5 .1 )。在N e t / 3 中, s u s e r函數(shù)用來(lái)判斷調(diào)用進(jìn)程是否有超級(jí)用戶權(quán)限,通過(guò)SS_PRIV標(biāo)志來(lái)判斷一個(gè)插口是否由超級(jí)用戶進(jìn)程產(chǎn)生
41、。 因?yàn)閞ip_usrreq在用socreate產(chǎn)生插口后立即檢查SS_PRIV標(biāo)志,所以我們認(rèn)為只有超級(jí)用戶進(jìn)程才能訪問(wèn)這個(gè)函數(shù)。 15.7getsock和sockargs函數(shù) 這兩個(gè)函數(shù)重復(fù)出現(xiàn)在插口系統(tǒng)調(diào)用中。 getsock的功能是將描述符映射到一個(gè)文件表項(xiàng)中, sockargs將進(jìn)程傳入的參數(shù)復(fù)制到內(nèi)核中的一個(gè)新分配的 mbuf中。這兩個(gè)函數(shù)都要檢查參數(shù)的正確性,如果參數(shù)不合法,則返回相應(yīng)的非 0差錯(cuò)代碼。 圖15-19列出了getsock函數(shù)的代碼。 7 5 4 - 7 6 7 getsock函數(shù)利用fdp查找描述符fdes指定的文件表項(xiàng), fdp是指向filedesc 結(jié)構(gòu)的指針
42、。getsock將打開的文件結(jié)構(gòu)指針賦給 fpp,并返回,或者當(dāng)出現(xiàn)下列情況時(shí)返回差錯(cuò)代碼:描述符的值超過(guò)了范圍而不是指向一個(gè)打開的文件;描述符沒(méi)有同插口建立聯(lián)系。 圖15-20列出了sockargs函數(shù)的代碼。 7 6 8 - 7 8 3 如圖15-4中所描述的, sockargs將進(jìn)程傳給系統(tǒng)調(diào)用的參數(shù)的指針從進(jìn)程復(fù)制到內(nèi)核而不是復(fù)制指針指向的數(shù)據(jù),這樣做是因?yàn)槊恳粋€(gè)參數(shù)的語(yǔ)義只有相對(duì)應(yīng)的系統(tǒng)調(diào)用才知道,而不是針對(duì)所有的系統(tǒng)調(diào)用。多個(gè)系統(tǒng)調(diào)用在調(diào)用 sockargs復(fù)制參數(shù)指針后,將指針指向的數(shù)據(jù)從進(jìn)程復(fù)制到內(nèi)核中新分配的 mbuf中。例如, sockargs將bind的第二個(gè)參 函 數(shù)
43、超級(jí)用戶 描 述 參考圖 進(jìn)程 插口 in_control in_control in_pcbbind ifioctl ifioctl rip_usrreq slopen分配接口地址、網(wǎng)絡(luò)掩碼、目的地址分配廣播地址 綁定到一個(gè)小于1024的Internet端口改變接口配置 配置多播地址(見(jiàn)下面的說(shuō)明)產(chǎn)生一個(gè)ICMP、IGMP或原始 IP插口將一個(gè)SLIP設(shè)備與一個(gè)tty設(shè)備聯(lián)系起來(lái) 圖 6-14 圖 6-22 圖22-22圖 4-29 圖12-11 圖32-10 圖5-9 362TCP/IP詳解 卷2:實(shí)現(xiàn) 數(shù)指向的本地插口地址從進(jìn)程復(fù)制到一個(gè) mbuf中。 下載圖15-19getsock
44、函數(shù)圖15-20sockargs 函數(shù) 如果數(shù)據(jù)不能存入一個(gè)mbuf中或無(wú)法分配mbuf,則sockargs返回EINVAL或ENOBUFS。注意,這里使用的是標(biāo)準(zhǔn)的 mbuf而不是分組首部的mbuf。copyin的功能是將數(shù)據(jù)從進(jìn)程復(fù)制到mbuf中。copyin返回的最常見(jiàn)的差錯(cuò)是EACCES,它表示進(jìn)程提供的地址不正確。 7 8 4 - 78 5當(dāng)出現(xiàn)差錯(cuò)時(shí),丟棄mbuf,并返回差錯(cuò)代碼。如果沒(méi)有差錯(cuò),通過(guò) mp返回指向 mbuf的指針, sockargs返回0。 7 8 6 - 7 9 4如果type等于MT_SONAME,則進(jìn)程傳入的是一個(gè)sockaddr結(jié)構(gòu)。sockargs 第 1
45、5 章 插 口 層363下載將剛復(fù)制的參數(shù)的長(zhǎng)度賦給內(nèi)部長(zhǎng)度變量 sa_len。這一點(diǎn)確保即使進(jìn)程沒(méi)有正確地初始化結(jié)構(gòu),結(jié)構(gòu)內(nèi)的大小也是正確的。 Net/3確實(shí)包含了一段代碼來(lái)支持在pre-4.3BSD Reno系統(tǒng)上編譯的應(yīng)用,這些應(yīng)用的sockaddr結(jié)構(gòu)中并沒(méi)有sa_len字段,但是圖15-20中沒(méi)有顯示這段代碼。 15.8bind系統(tǒng)調(diào)用 bind系統(tǒng)調(diào)用將一個(gè)本地的網(wǎng)絡(luò)運(yùn)輸層地址和插口聯(lián)系起來(lái)。一般來(lái)說(shuō),作為客戶的進(jìn)程并不關(guān)心它的本地地址是什么。在這種情況下,進(jìn)程在進(jìn)行通信之前沒(méi)有必要調(diào)用 bind; 內(nèi)核會(huì)自動(dòng)為其選擇一個(gè)本地地址。 服務(wù)器進(jìn)程則總是需要綁定到一個(gè)已知的地址上。所以
46、,進(jìn)程在接受連接 (TCP)或接收數(shù)據(jù)報(bào)(UDP)之前必須調(diào)用bind,因?yàn)榭蛻暨M(jìn)程需要同已知的地址建立連接或發(fā)送數(shù)據(jù)報(bào)到已知的地址。 插口的外部地址由connect指定或由允許指定外部地址的寫調(diào)用 (sendto或sendmsg) 指定。 圖15-21列出了bind調(diào)用的代碼。 圖15-21bind 函數(shù)7 0 - 8 2bind調(diào)用的參數(shù)有(在bind_args結(jié)構(gòu)中):s,插口描述符; name,包含傳輸?shù)刂?如,sockaddr_in結(jié)構(gòu))的緩存指針;和namelen,緩存大小。 8 3 - 9 0getsock返回描述符的file結(jié)構(gòu),sockargs將本地地址復(fù)制到mbuf中,so
47、bind將進(jìn)程指定的地址同插口聯(lián)系起來(lái)。在bind返回sobind的結(jié)果之前,釋放保存地址的mbuf。從技術(shù)上講,一個(gè)描述符,如 s,標(biāo)識(shí)一個(gè)同socket結(jié)構(gòu)相關(guān)聯(lián)的file結(jié)構(gòu),而它本身并不是一個(gè)socket結(jié)構(gòu)。將這種描述符看作插口是為了簡(jiǎn)化我們的討論。 我們將在下面的討論中經(jīng)??吹竭@種模式:進(jìn)程指定的參數(shù)被復(fù)制到 mbuf,必要時(shí)還要 364TCP/IP詳解 卷2:實(shí)現(xiàn) 下載進(jìn)行處理,然后在系統(tǒng)調(diào)用返回之前釋放 mbuf。雖然mbuf是為方便處理網(wǎng)絡(luò)數(shù)據(jù)分組而設(shè)計(jì)的,但是將它們用作一般的動(dòng)態(tài)內(nèi)存分配機(jī)制也是有效的。 bind說(shuō)明的另一種模式是:許多系統(tǒng)調(diào)用不使用 retval。在第15
48、.4節(jié)中我們已提到過(guò), 在syscall將控制交給相應(yīng)的系統(tǒng)調(diào)用之前總是將 retval清0。如果0不是合適的返回值, 系統(tǒng)調(diào)用并不需要修改retval。 sobind函數(shù) 如圖15-22所示,sobind是一個(gè)封裝器,它給與插口相關(guān)聯(lián)的協(xié)議發(fā)送 PRU_BIND請(qǐng)求。 圖15-22 sobind 函數(shù)7 8 - 8 9sobind發(fā)送PRU_BIND請(qǐng)求。如果請(qǐng)求成功,將本地地址nam同插口聯(lián)系起來(lái);否 則,返回差錯(cuò)代碼。15.9listen系統(tǒng)調(diào)用 listen系統(tǒng)調(diào)用的功能是協(xié)議進(jìn)程準(zhǔn)備接收插口上的連接請(qǐng)求,如圖 15-23所示。它同時(shí)也指定插口上可以排隊(duì)等待的連接數(shù)的門限值。超過(guò)門限值
49、時(shí),插口層將拒絕進(jìn)入的連接請(qǐng)求排隊(duì)等待。當(dāng)這種情況出現(xiàn)時(shí), TCP將忽略進(jìn)入的連接請(qǐng)求。進(jìn)程可以通過(guò)調(diào)用accept (第15.11節(jié))來(lái)得到隊(duì)列中的連接。 圖15-23 listen 系統(tǒng)調(diào)用 第 15 章 插 口 層365下載9 1 - 9 8 listen系統(tǒng)調(diào)用有兩個(gè)參數(shù):一個(gè)指定插口描述符;另一個(gè)指定連接隊(duì)列門限值。 9 9 - 1 0 5 getsock返回描述符s的file結(jié)構(gòu),solisten將請(qǐng)求傳遞給協(xié)議層。 solisten函數(shù) solisten函數(shù)發(fā)送PRU_LISTEN請(qǐng)求,并使插口準(zhǔn)備接收連接,如圖15-24所示。 9 0 - 1 0 9 在solisten發(fā)送PR
50、U_LISTEN請(qǐng)求且pr_usrreq返回后,標(biāo)識(shí)插口處于準(zhǔn)備接收連接狀態(tài)。如果當(dāng)pr_usrreq返回時(shí)有連接正在連接隊(duì)列中,則不設(shè)置SS_ACCEPTCONN標(biāo)志。計(jì)算存放進(jìn)入連接的隊(duì)列的最大值,并賦給 so_qlimit。Net/3默認(rèn)設(shè)置下限為0,上限為5(SOMAXCONN)條連接。 圖15-24 solisten 函數(shù)15.10tsleep和wakeup函數(shù) 當(dāng)一個(gè)在內(nèi)核中執(zhí)行的進(jìn)程因?yàn)榈貌坏絻?nèi)核資源而不能繼續(xù)執(zhí)行時(shí),它就調(diào)用 tsleep等待。tsleep的原型是: int tsleep(caddr_t chan, int pri, char *mesg, int timeo)
51、;tsleep的第一個(gè)參數(shù)chan,被稱之為等待通道。它標(biāo)志進(jìn)程等待的特定資源或。許多進(jìn)程能同時(shí)在同一個(gè)等待通道上睡眠。當(dāng)資源可用或待通道作為唯一的參數(shù)傳入。 wakeup的原型是: void wakeup(caddr_t chan);出現(xiàn)時(shí),內(nèi)核調(diào)用 wakeup,并將等所有等待在該通道上的的進(jìn)程均被喚醒,并被設(shè)置成運(yùn)行狀態(tài)。當(dāng)每一個(gè)進(jìn)程均恢復(fù)執(zhí)行時(shí),內(nèi)核安排tsleep返回。 當(dāng)進(jìn)程被喚醒時(shí), tsleep的第二個(gè)參數(shù)pri指定被喚醒進(jìn)程的優(yōu)先級(jí)。 pri中還包括幾個(gè)用于t s l e e p的可選的控制標(biāo)志。通過(guò)設(shè)置 p r i 中的P C A T C H標(biāo)志,當(dāng)一個(gè)信號(hào)出現(xiàn)時(shí), tsl
52、eep也返回。mesg是一個(gè)說(shuō)明調(diào)用tsleep的字符串,它將被放在調(diào)用報(bào)文或ps的輸出中。 366TCP/IP詳解 卷2:實(shí)現(xiàn) 下載timeo設(shè)置睡眠間隔的上限值,其單位是時(shí)鐘滴答。圖15-25列出了tsleep的返回值。 因?yàn)樗械却谕坏却ǖ郎系倪M(jìn)程均被wakeup喚醒,所以我們總是看到在一個(gè)循環(huán)中調(diào)用tsleep。每一個(gè)被喚醒的進(jìn)程在繼續(xù)執(zhí)行之前必須檢查等待的資源是否可得到,因?yàn)榱硪粋€(gè)被喚醒的進(jìn)程可能已經(jīng)先一步得到了資源。如果仍然得不到資源,進(jìn)程再調(diào)用tsleep等待。圖15-25 tsleep 的返回值多個(gè)進(jìn)程在一個(gè)插口上睡眠等待的情況是不多見(jiàn)的,所以,通常情況下,一次調(diào)用 wa
53、keup只有一個(gè)進(jìn)程被內(nèi)核喚醒。 關(guān)于睡眠和喚醒機(jī)制的詳細(xì)討論請(qǐng)參考Leffler et al. 1989。 舉例多個(gè)進(jìn)程在同一個(gè)等待通道上睡眠的一個(gè)例子是:讓多個(gè)服務(wù)器進(jìn)程讀同一個(gè) UDP插口。每一個(gè)服務(wù)器都調(diào)用recvfrom,并且只要沒(méi)有數(shù)據(jù)可讀就在tsleep中等待。當(dāng)一個(gè)數(shù)據(jù)報(bào)到達(dá)插口時(shí),插口層調(diào)用wakeup,所有等待進(jìn)程均被放入運(yùn)行隊(duì)列。第一個(gè)運(yùn)行的服務(wù)器讀取了數(shù)據(jù)報(bào)而其他的服務(wù)器則再次調(diào)用tsleep。在這種情況下,不需要每一個(gè)數(shù)據(jù)報(bào)啟動(dòng)一個(gè)新的進(jìn)程,就可將進(jìn)入的數(shù)據(jù)報(bào)分發(fā)到多個(gè)服務(wù)器。這種技術(shù)同樣可以用來(lái)處理 TCP的連接請(qǐng)求, 只需讓多個(gè)進(jìn)程在同一個(gè)插口上調(diào)用accept。
54、這種技術(shù)在Comer and Stevens 1993中描述。 15.11accept系統(tǒng)調(diào)用 調(diào)用listen后,進(jìn)程調(diào)用accept等待連接請(qǐng)求。accept返回一個(gè)新的描述符,指向一個(gè)連接到客戶的新的插口。原來(lái)的插口 s仍然是未連接的,并準(zhǔn)備接收下一個(gè)連接。如果name 指向一個(gè)正確的緩存, accept就會(huì)返回對(duì)方的地址。 處理連接的細(xì)節(jié)由與插口相關(guān)聯(lián)的協(xié)議來(lái)完成。對(duì)于TCP而言,當(dāng)一條連接已經(jīng)被建立(即,三次握手已經(jīng)完成)時(shí),就插口層。對(duì)于其他的協(xié)議,如 OSI的TP4,只要一個(gè)連接請(qǐng)求到達(dá),tsleep就返回。當(dāng)進(jìn)程通過(guò)在插口上發(fā)送或接收數(shù)據(jù)來(lái)顯式證實(shí)連接后,連接則算完成。 圖15-26說(shuō)明accept的實(shí)現(xiàn)。 圖15-26 accept 系統(tǒng)調(diào)用tsleep()描 述 0EWOULDBLOCK ERESTART EINTR進(jìn)程被一個(gè)匹配的wakeup喚醒 進(jìn)程在睡眠timeo個(gè)時(shí)鐘滴答后,在匹配的wakeup調(diào)用之前被喚醒在睡
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年技術(shù)投資合作協(xié)議
- 民間借款協(xié)議書的風(fēng)險(xiǎn)防范
- 數(shù)字作品版權(quán)協(xié)議模板
- 2024新合作設(shè)立分公司協(xié)議范本
- 2024版工程中介居間合同樣本
- 房產(chǎn)代理合同范本
- 勞動(dòng)合同續(xù)簽的溝通技巧分享
- 股權(quán)質(zhì)押合同新格式
- 蘇教版小學(xué)數(shù)學(xué)四年級(jí)下冊(cè)《用數(shù)對(duì)確定位置》公開課教學(xué)設(shè)計(jì)及說(shuō)課稿
- 策略性合作合同模板及解讀
- 期中測(cè)試卷-2024-2025學(xué)年統(tǒng)編版語(yǔ)文二年級(jí)上冊(cè)
- 2024年新高考Ⅰ卷、Ⅱ卷、甲卷詩(shī)歌鑒賞試題講評(píng)課件
- 10以內(nèi)口算題每頁(yè)50道
- 健康科普宣教課件
- “單腳起跳、雙腳落地”案理分析
- 建筑施工安全生產(chǎn)專項(xiàng)整治三年行動(dòng)實(shí)施方案
- 管卡管件標(biāo)準(zhǔn)2010
- FMPS多維完美主義量表中文版及英文原版
- 砼質(zhì)量缺陷修補(bǔ)方案
- 美國(guó)的人才機(jī)制
- 電壓和電阻復(fù)習(xí)課件
評(píng)論
0/150
提交評(píng)論