- 論壇徽章:
- 0
|
進(jìn)程間通信
1. 管道 (pipe) 的限制
UNIX 管道要求所有的通信進(jìn)程都源自一個(gè)共同的父進(jìn)程。因此,管道的使用造成了一些系統(tǒng)在設(shè)計(jì)上采用了有些不自然的結(jié)構(gòu)。
2.naive/sophisticated process
所謂一個(gè)單純進(jìn)程 (navie process) 就是僅靠從標(biāo)準(zhǔn)輸入文件中讀數(shù)據(jù)和向標(biāo)準(zhǔn)輸出文件寫(xiě)數(shù)據(jù)來(lái)完成工作的進(jìn)程。
而一個(gè)成熟的進(jìn)程 (sophisticated process) 則了解和掌握了操作系統(tǒng)提供的更多接口,并且它能用掌握的這些信息完成自己的工作。
3.IPC 在設(shè)計(jì)上應(yīng)支持的特性
透明性: IPC 應(yīng)該和這些通信進(jìn)程是否在同一臺(tái)機(jī)器上沒(méi)有關(guān)系。
高效性
兼容性:現(xiàn)有的單純進(jìn)程應(yīng)該無(wú)需改動(dòng)便可以在分布式環(huán)境里使用。
4. 通信語(yǔ)義與屬性
通信的語(yǔ)義包括:可靠數(shù)據(jù)傳輸?shù)拇鷥r(jià) (cost), 支持組播 (multicast) 傳輸,以及能夠傳送訪問(wèn)權(quán)限或能力等等。
其屬性有:
數(shù)據(jù)的有序傳送
數(shù)據(jù)的無(wú)重復(fù)發(fā)送
數(shù)據(jù)的可靠傳送
面向連接的通信
信息分界的保存
對(duì)帶外消息的支持
帶外 (out-of-band) 消息是在正常傳入流 ( 即帶內(nèi)數(shù)據(jù) ) 之外發(fā)送給接收方的消息。通常是在緊急或異常情況下發(fā)送它。
5. 常用套接口
1> 數(shù)據(jù)報(bào)套接口 (datagram socket) 提供了一個(gè)不可靠的,無(wú)連接數(shù)據(jù)包通信模型;
2> 流套接口 (stream socket) 提供了一個(gè)可靠的,面向連接的字節(jié)流模型,支持帶外數(shù)據(jù)發(fā)送;
3> 有序數(shù)據(jù)包套接口 (sequenced packet socket) 提供了一個(gè)有序,可靠,無(wú)重復(fù)的機(jī)遇連接的通信模型。
連接是一種由協(xié)議使用的機(jī)制,協(xié)議用它來(lái)避免在每個(gè)發(fā)送的數(shù)據(jù)包上都帶套接口標(biāo)識(shí)。兩端都各自保留狀態(tài)信息。另一方面,無(wú)連接的同學(xué)要求在每一次傳送時(shí)都帶上源和目的地址。
6. 使用套接口
( UNP 才是關(guān)于 socket 的最佳參考資料)
創(chuàng)建套接口
int sock, domain = AF_INET, type = SOCK_STREAM, protocol = 0;
sock = socket(domain, type, protocol);
初始化一個(gè)連接
int error;
int sock; /* Previously created by a socket() call. */
struct sockaddr_in rmtaddr; /* Assigned by the program. */
int rmtaddrlen = sizeof (struct sockaddr_in);
error =
connect(sock, (struct sockaddr *)&rmtaddr, rmtaddrlen);
客戶端就到吃為止了,而服務(wù)器端則需把一個(gè)地址同一個(gè)套接口綁定
int error;
int sock;
struct sockaddr_in addr;
int addrlen = sizeof (struct sockaddr_in);
error =
bind(sock, (struct sockaddr*)&localaddr, localaddrlen);
監(jiān)聽(tīng)套接口
int error, sock, backlog;
error = listen(sock, backlog);
接受傳入的連接
int newsock, sock;
struct sockaddr_in clientaddr;
int clientaddrlen = sizeof(struct sockaddr_in);
newsock =
accept(sock, (struct sockaddr *)&clientaddr, clientaddrlen);
在套接口上發(fā)送和接受數(shù)據(jù)的例程
Routine
Connected
Disconnected
Address Info
read
Y
N
N
readv
Y
N
N
write
Y
N
N
writev
Y
N
N
recv
Y
Y
N
send
Y
Y
N
recvmsg
Y
Y
Y
sendmsg
Y
Y
Y
Sendmsg 與 recvmsg 還可以傳遞有特殊解釋的輔助數(shù)據(jù)或者控制信息
![]()
IPC 覆蓋在連網(wǎng)機(jī)制上,應(yīng)用程序的數(shù)據(jù)流通過(guò)套接口層到達(dá)網(wǎng)
絡(luò)層,反之亦然。套接口層所需的狀態(tài)完全封裝在它自己的里面,而所有與協(xié)議有關(guān)的狀態(tài)都保存在專(zhuān)門(mén)支持該協(xié)議的輔助數(shù)據(jù)結(jié)構(gòu)中。而存儲(chǔ)傳輸數(shù)據(jù)的責(zé)任則從
套接口層下放到網(wǎng)絡(luò)層。始終堅(jiān)持這原則有助于簡(jiǎn)化存儲(chǔ)管理的細(xì)節(jié)。
![]()
套接口層支持的例程
Routine
Function
socreate()
create a new socket
sobind()
bind a name to a socket
solisten()
mark a socket as listening for connection requests
soclose()
close a socket
soabort()
abort connection on a socket
soaccept()
accept a pending connection on a socket
soconnect()
initiate a connection to another socket
soconnect2()
create a connection between two sockets
sodisconnect()
initiate a disconnect on a connected socket
sosend()
send data
soreceive()
receive data
soshutdown()
shut down data transmission or reception
sosetopt()
set the value of a socket option
sogetopt()
get the value of a socket option
7. IPC 和網(wǎng)絡(luò)協(xié)議對(duì)內(nèi)存管理模式的要求
需要內(nèi)存的可能是想通信協(xié)議數(shù)據(jù)包這樣長(zhǎng)度不定的結(jié)構(gòu)。
數(shù)據(jù)包和其他數(shù)據(jù)對(duì)象必須在等待發(fā)送和接受時(shí)排成隊(duì)列。
8.mbuf
mbuf 即內(nèi)存緩沖區(qū) (memory buffer) ,它的大小隨著它所保存的內(nèi)容不同而變化。所有的 mbuf 都包含一個(gè)大小固定的 m_hdr 結(jié)構(gòu),這個(gè)結(jié)構(gòu)記錄了各種有關(guān) mbuf 的信息位。一個(gè)只含數(shù)據(jù)的 mbuf 有 234 字節(jié)的空間 (mbuf 總長(zhǎng) 256 字節(jié),減去 mbuf 頭 [m_hdr] 的 22 字節(jié) ) 。
![]()
把一則消息的內(nèi)容向上傳遞給更高層的處理模塊之前,協(xié)議要例行地剝?nèi)ゴ讼⑶昂蟮膮f(xié)議信息;而在向下傳遞消息時(shí),又要加上協(xié)議信息。
由 m_next 鏈接器阿里的一個(gè) mbuf 結(jié)構(gòu)的集合稱為一個(gè)鏈;而由 m_nextpkt 鏈接起來(lái)的若干個(gè) mbuf 鏈則被稱為一個(gè)隊(duì)列。
mbuf 除了 m_hdr 外還可以只用標(biāo)志指定第二組數(shù)據(jù)包頭
![]()
Memory-buffer (mbuf) data structure with M_PKTHDR
![]()
Memory-buffer (mbuf) data structure with external storage
9.mbuf 的數(shù)據(jù)域長(zhǎng)度固定不可變的原因
長(zhǎng)度固定使得內(nèi)存的碎片化降至最低
要求通信協(xié)議頻繁地在已有的數(shù)據(jù)區(qū)前后添加協(xié)議頭,對(duì)數(shù)據(jù)區(qū)進(jìn)行分割,或者是從一個(gè)數(shù)據(jù)區(qū)的開(kāi)始或末尾截取數(shù)據(jù)。 Mbuf 在設(shè)計(jì)必須能夠在熱和可能的時(shí)候無(wú)需重新分配或復(fù)制內(nèi)存,就可以處理這樣的變化。
如果 mbuf 打大小不固定的話,一些相關(guān)函數(shù)的執(zhí)行開(kāi)銷(xiāo)將會(huì)大得多。
10. 為了支持 SMP 對(duì) mbuf 的改進(jìn)
每個(gè) CPU 都有自己的存放 mbuf 和 mbuf 簇的鏈表。還有一個(gè)通用的 mbuf 和 mbuf 簇的鏈表,當(dāng)每個(gè) CPU 自己的鏈表使用完了,就要嘗試從那個(gè)通用鏈表分配內(nèi)存,而當(dāng)每個(gè) CPU 自己的鏈表都有足夠空間了,就要把內(nèi)存釋放回該通用鏈表。
11.socket 與通信域的相關(guān)數(shù)據(jù)結(jié)構(gòu)
1> 系統(tǒng)支持的套接口類(lèi)型
Name
Type
Properties
SOCK_STREAM
stream
reliable, sequenced, data transfer; may support out-of-band data
SOCK_DGRAM
datagram
unreliable, unsequenced, data transfer, with message boundaries preserved
SOCK_SEQPACKET
sequenced packet
reliable, sequenced, data transfer, with message boundaries preserved
SOCK_RAW
raw
direct access to the underlying communication protocols
2>domain 結(jié)構(gòu)
![]()
其中 dom_family 項(xiàng)去確定了通信域所使用的地址族
Name
Description
AF_LOCAL
(AF_UNIX) local communication
AF_INET
Internet (TCP/IP)
AF_INET6
Internet Version 6 (TCP/IPv6)
AF_NS
Xerox Network System (XNS) architecture
AF_ISO
OSI network protocols
AF_CCITT
CCITT protocols, e.g., X.25
AF_SNA
IBM System Network Architecture (SNA)
AF_DLI
direct link interface
AF_LAT
local-area-network terminal interface
AF_APPLETALK
AppleTalk network
AF_ROUTE
communication with kernel routing layer
AF_LINK
raw link-layer access
AF_IPX
Novell Internet protocol
3>socket 結(jié)構(gòu)
![]()
Socket 包含的信息有關(guān)它們的類(lèi)型,使用的支持協(xié)議以及它們的狀態(tài)。
State
Description
SS_NOFDREF
no file-table reference
SS_ISCONNECTED
connected to a peer
SS_ISCONNECTING
in process of connecting to peer
SS_ISDISCONNECTING
in process of disconnecting from peer
SS_CANTSENDMORE
cannot send more data to peer
SS_CANTRCVMORE
cannot receive more data from peer
SS_RCVATMARK
at out-of-band mark on input
SS_ISCONFIRMING
peer awaiting connection confirmation
SS_NBIO
nonblocking I/O
SS_ASYNC
asynchronous I/O notification
SS_INCOMP
connection is incomplete and not yet accepted
SS_COMP
connection is complete but not yet accepted
SS_ISDISCONNECTED
socket is disconnected from peer
用來(lái)接受傳入連接請(qǐng)求的套接口有兩個(gè)與連接請(qǐng)求相關(guān)的套接口隊(duì)列。由 so_incomp 字段開(kāi)頭的套接口鏈表代表了一個(gè)由連接組成的隊(duì)列,必須在協(xié)議層完成這些連接后才能將它們返回。 so_comp 字段開(kāi)頭的則是一個(gè)準(zhǔn)備返回給監(jiān)聽(tīng)進(jìn)程的套接口鏈表。
4> 套接口地址
![]()
![]()
12. 高位線、低位線
為了避免耗盡資源,對(duì)于在一個(gè)套接口數(shù)據(jù)緩沖區(qū)中排隊(duì)的數(shù)據(jù)字節(jié)數(shù),也就是數(shù)據(jù)所能使用的存儲(chǔ)空間量,套接口都給它們?cè)O(shè)置了上界。這個(gè)高位線 (high watermark) 由協(xié)議進(jìn)行初始化,當(dāng)然一個(gè)應(yīng)用程序也可以改變這個(gè)值,但它不能超過(guò)系統(tǒng)最大值 ( 通常是 256KB) 。網(wǎng)絡(luò)協(xié)議能夠檢查高位線,并將這個(gè)值用于流控策略。在每個(gè)套接口數(shù)據(jù)緩沖區(qū)中還有一個(gè)低位線 (low watermark) 。低位線是滿足一次數(shù)據(jù)接收請(qǐng)求所需要的最少字節(jié)數(shù),應(yīng)用程序可以通過(guò)它控制數(shù)據(jù)流。
13. 建立連接
進(jìn)程對(duì)接期間套接口的狀態(tài)轉(zhuǎn)換圖
![]()
Socket state transitions during process rendezvous
在套接口上排隊(duì)以等待 accept() 調(diào)用的鏈接
![]()
在連接建立的過(guò)程中,套接口的狀態(tài)有套接口層和支持協(xié)議層聯(lián)合管理。一個(gè)協(xié)議永遠(yuǎn)不會(huì)直接改變套接口的狀態(tài)值;為促進(jìn)模塊化,所有的改變都由替代套接口
例程來(lái)執(zhí)行。這些例程按照指示改變套接口的狀態(tài),并通知任何處于等待中的進(jìn)程。支持協(xié)議層從來(lái)不直接使用同步或信號(hào)機(jī)制。異步檢查出的錯(cuò)誤被傳遞到一個(gè)套
接口的 so_error 項(xiàng)中。
14. 傳送 / 接收數(shù)據(jù)
套接口層主要的工作就是發(fā)送和接收數(shù)據(jù)。必須注意,除了可以選擇加記錄邊界之外,套接口層本身明確不允許在通過(guò)套接口傳輸或接收的數(shù)據(jù)上施加任何結(jié)構(gòu)。在整個(gè) IPC 中,對(duì)任何數(shù)據(jù)的解釋或者結(jié)構(gòu)化在邏輯上都獨(dú)立于通信域的實(shí)現(xiàn)。
對(duì)于那些要保證數(shù)據(jù)可靠傳遞的套接口來(lái)說(shuō),協(xié)議通常要在套接口的發(fā)送隊(duì)列里保留所有要發(fā)送數(shù)據(jù)的一個(gè)副本,直到接收方確認(rèn)收到這些數(shù)據(jù)為止。那些不保證數(shù)據(jù)一定發(fā)送到的協(xié)議則通常從 sosend 中接受數(shù)據(jù),然后將其直接發(fā)往目的地,不保存任何副本。但是 sosend() 自己并不區(qū)分可靠與不可靠傳輸。
在接受數(shù)據(jù)緩沖中出現(xiàn)的數(shù)據(jù)組織通常有 3 中情況:分別針對(duì)流,數(shù)據(jù)報(bào)以及有序數(shù)據(jù)包的套接口。在一般情況下,接收數(shù)據(jù)緩沖區(qū)是按照消息鏈表的方式來(lái)組織的。
![]()
Data queueing for datagram socket
15. 關(guān)閉套接口
1> 對(duì)可靠協(xié)議的 close 隱含的語(yǔ)義
當(dāng)一個(gè)承諾可靠傳送數(shù)據(jù)的套接口在關(guān)閉時(shí)還有排隊(duì)等待發(fā)送的數(shù)據(jù),或者還有等待確認(rèn)收到的數(shù)據(jù),套接口就必須為了 close 調(diào)用, ( 可能無(wú)限次地 ) 嘗試發(fā)送這些數(shù)據(jù),以保證套接口承諾的可靠傳遞數(shù)據(jù)的語(yǔ)義。如果套接口為了使 close 調(diào)用成功完成而丟棄數(shù)據(jù)的話,它就違背了關(guān)于可靠傳遞數(shù)據(jù)的承諾。根據(jù) close 隱含語(yǔ)義,丟棄數(shù)據(jù)就可能導(dǎo)致這些進(jìn)程在網(wǎng)絡(luò)環(huán)境中的工作不可靠。然而,如果一直到所有的數(shù)據(jù)都被成功發(fā)送后才關(guān)閉套接口,那么,在有些通信域中, close 調(diào)用可能永遠(yuǎn)不會(huì)結(jié)束。
2> 關(guān)閉套接口時(shí)其狀態(tài)轉(zhuǎn)換圖
![]()
16. 本地 IPC
本地 IPC 的用戶級(jí) API
Subsystem
Create
Control
Communicate
semaphores
semget
semctl
semop
message queues
msgget
mesgctl
msgrcv, msgsnd
shared memory
shmget
shmctl, shmdt
n/a
消息隊(duì)列天生就是半雙工的,在通信端點(diǎn)之間傳遞的消息里帶有一個(gè)類(lèi)型和一個(gè)數(shù)據(jù)區(qū)。
![]()
對(duì)于共享內(nèi)存,當(dāng)進(jìn)程用完共享內(nèi)存的時(shí)候,它就使用系統(tǒng)調(diào)用 shmdt 把共享內(nèi)存從它的進(jìn)程空間中剝離。這個(gè)例程不會(huì)釋放共享內(nèi)存,因?yàn)槠渌M(jìn)程可能還在使用它,但是它會(huì)解除調(diào)用它的進(jìn)程對(duì)虛擬內(nèi)存的映射。
本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u/16651/showart_2005062.html |
|