? ? ? ?進(jìn)程間通信概述
進(jìn)程通信的目的
數(shù)據(jù)傳輸
一個(gè)進(jìn)程需要將它的數(shù)據(jù)發(fā)送給另一個(gè)進(jìn)程,發(fā)送的數(shù)據(jù)量在一個(gè)字節(jié)到幾M字節(jié)之間
共享數(shù)據(jù)
多個(gè)進(jìn)程想要操作共享數(shù)據(jù),一個(gè)進(jìn)程對(duì)共享數(shù)據(jù)
通知事
一個(gè)進(jìn)程需要向另一個(gè)或一組進(jìn)程發(fā)送消息,通知它(它們)發(fā)生了某種事件(如進(jìn)程終止時(shí)要通知父進(jìn)程)。
資源共享
多個(gè)進(jìn)程之間共享同樣的資源。為了作到這一點(diǎn),需要內(nèi)核提供鎖和同步機(jī)制。
進(jìn)程控制
有些進(jìn)程希望完全控制另一個(gè)進(jìn)程的執(zhí)行(如Debug進(jìn)程),此時(shí)控制進(jìn)程希望能夠攔截另一個(gè)進(jìn)程的所有陷入和異常,并能夠及時(shí)知道它的狀態(tài)改變。
Linux 進(jìn)程間通信(IPC)的發(fā)展
linux下的進(jìn)程通信手段基本上是從Unix平臺(tái)上的進(jìn)程通信手段繼承而來的。而對(duì)Unix發(fā)展做出重大貢獻(xiàn)的兩大主力AT&T的貝爾實(shí)驗(yàn)室及BSD(加州大學(xué)伯克利分校的伯克利軟件發(fā)布中心)在進(jìn)程間通信方面的側(cè)重點(diǎn)有所不同。 前者對(duì)Unix早期的進(jìn)程間通信手段進(jìn)行了系統(tǒng)的改進(jìn)和擴(kuò)充,形成了“system V IPC”,通信進(jìn)程局限在單個(gè)計(jì)算機(jī)內(nèi); 后者則跳過了該限制,形成了基于套接口(socket)的進(jìn)程間通信機(jī)制。 Linux則把兩者繼承了下來
1
2
3
4
5
6
7
8
早期UNIX進(jìn)程間通信
基于System V進(jìn)程間通信
基于Socket進(jìn)程間通信
POSIX進(jìn)程間通信。
UNIX進(jìn)程間通信方式包括:管道、FIFO、信號(hào)。
System V進(jìn)程間通信方式包括:System V消息隊(duì)列、System V信號(hào)燈、System V共享內(nèi)存
POSIX進(jìn)程間通信包括:posix消息隊(duì)列、posix信號(hào)燈、posix共享內(nèi)存。
由于Unix版本的多樣性,電子電氣工程協(xié)會(huì)(IEEE)開發(fā)了一個(gè)獨(dú)立的Unix標(biāo)準(zhǔn),這個(gè)新的ANSI Unix標(biāo)準(zhǔn)被稱為計(jì)算機(jī)環(huán)境的可移植性操作系統(tǒng)界面(POSIX)?,F(xiàn)有大部分Unix和流行版本都是遵循POSIX標(biāo)準(zhǔn)的,而Linux從一開始就遵循POSIX標(biāo)準(zhǔn);BSD并不是沒有涉足單機(jī)內(nèi)的進(jìn)程間通信(socket本身就可以用于單機(jī)內(nèi)的進(jìn)程間通信)。事實(shí)上,很多Unix版本的單機(jī)IPC留有BSD的痕跡,如4.4BSD支持的匿名內(nèi)存映射、4.3+BSD對(duì)可靠信號(hào)語(yǔ)義的實(shí)現(xiàn)等等。
1
2
3
4
linux使用的進(jìn)程間通信方式
管道(pipe),流管道(s_pipe)和有名管道(FIFO)
信號(hào)(signal)
消息隊(duì)列
共享內(nèi)存
信號(hào)量
套接字(socket)
管道( pipe )
管道這種通訊方式有兩種限制,一是半雙工的通信,數(shù)據(jù)只能單向流動(dòng),二是只能在具有親緣關(guān)系的進(jìn)程間使用。進(jìn)程的親緣關(guān)系通常是指父子進(jìn)程關(guān)系。
流管道s_pipe: 去除了第一種限制,可以雙向傳輸.
管道可用于具有親緣關(guān)系進(jìn)程間的通信,命名管道:name_pipe克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關(guān)系進(jìn)程間的通信;
信號(hào)量( semophore )
信號(hào)量是一個(gè)計(jì)數(shù)器,可以用來控制多個(gè)進(jìn)程對(duì)共享資源的訪問。它常作為一種鎖機(jī)制,防止某進(jìn)程正在訪問共享資源時(shí),其他進(jìn)程也訪問該資源。因此,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段。
信號(hào)是比較復(fù)雜的通信方式,用于通知接受進(jìn)程有某種事件發(fā)生,除了用于進(jìn)程間通信外,進(jìn)程還可以發(fā)送信號(hào)給進(jìn)程本身;linux除了支持Unix早期信號(hào)語(yǔ)義函數(shù)sigal外,還支持語(yǔ)義符合Posix.1標(biāo)準(zhǔn)的信號(hào)函數(shù)sigaction(實(shí)際上,該函數(shù)是基于BSD的,BSD為了實(shí)現(xiàn)可靠信號(hào)機(jī)制,又能夠統(tǒng)一對(duì)外接口,用sigaction函數(shù)重新實(shí)現(xiàn)了signal函數(shù));
消息隊(duì)列( message queue )
消息隊(duì)列是由消息的鏈表,存放在內(nèi)核中并由消息隊(duì)列標(biāo)識(shí)符標(biāo)識(shí)。消息隊(duì)列克服了信號(hào)傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點(diǎn)。
消息隊(duì)列是消息的鏈接表,包括Posix消息隊(duì)列system V消息隊(duì)列。有足夠權(quán)限的進(jìn)程可以向隊(duì)列中添加消息,被賦予讀權(quán)限的進(jìn)程則可以讀走隊(duì)列中的消息。消息隊(duì)列克服了信號(hào)承載信息量少,管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點(diǎn)。
信號(hào) ( singal )
信號(hào)是一種比較復(fù)雜的通信方式,用于通知接收進(jìn)程某個(gè)事件已經(jīng)發(fā)生。
主要作為進(jìn)程間以及同一進(jìn)程不同線程之間的同步手段。
共享內(nèi)存( shared memory )
共享內(nèi)存就是映射一段能被其他進(jìn)程所訪問的內(nèi)存,這段共享內(nèi)存由一個(gè)進(jìn)程創(chuàng)建,但多個(gè)進(jìn)程都可以訪問。共享內(nèi)存是最快的 IPC(Inter-Process Communication) 方式,它是針對(duì)其他進(jìn)程間通信方式運(yùn)行效率低而專門設(shè)計(jì)的。它往往與其他通信機(jī)制,如信號(hào)量,配合使用,來實(shí)現(xiàn)進(jìn)程間的同步和通信。
使得多個(gè)進(jìn)程可以訪問同一塊內(nèi)存空間,是最快的可用IPC形式。是針對(duì)其他通信機(jī)制運(yùn)行效率較低而設(shè)計(jì)的。往往與其它通信機(jī)制,如信號(hào)量結(jié)合使用,來達(dá)到進(jìn)程間的同步及互斥。
套接字( socket )
套解口也是一種進(jìn)程間通信機(jī)制,與其他通信機(jī)制不同的是,它可用于不同機(jī)器間的進(jìn)程通信
更為一般的進(jìn)程間通信機(jī)制,可用于不同機(jī)器之間的進(jìn)程間通信。起初是由Unix系統(tǒng)的BSD分支開發(fā)出來的,但現(xiàn)在一般可以移植到其它類Unix系統(tǒng)上:Linux和System V的變種都支持套接字。
進(jìn)程間通信各種方式效率比較
類型無連接可靠流控制記錄消息類型優(yōu)先級(jí)普通PIPENYY?N流PIPENYY?N命名PIPE(FIFO)NYY?N消息隊(duì)列NYY?Y信號(hào)量NYY?Y共享存儲(chǔ)NYY?YUNIX流SOCKETNYY?NUNIX數(shù)據(jù)包SOCKETYYN?N
注:無連接: 指無需調(diào)用某種形式的OPEN,就有發(fā)送消息的能力流控制:如果系統(tǒng)資源短缺或者不能接收更多消息,則發(fā)送進(jìn)程能進(jìn)行流量控制
1
2
3
4
各種通信方式的比較和優(yōu)缺點(diǎn)
管道:速度慢,容量有限,只有父子進(jìn)程能通訊
FIFO:任何進(jìn)程間都能通訊,但速度慢
消息隊(duì)列:容量受到系統(tǒng)限制,且要注意第一次讀的時(shí)候,要考慮上一次沒有讀完數(shù)據(jù)的問題
信號(hào)量:不能傳遞復(fù)雜消息,只能用來同步
共享內(nèi)存區(qū):能夠很容易控制容量,速度快,但要保持同步,比如一個(gè)進(jìn)程在寫的時(shí)候,另一個(gè)進(jìn)程要注意讀寫的問題,相當(dāng)于線程中的線程安全,當(dāng)然,共享內(nèi)存區(qū)同樣可以用作線程間通訊,不過沒這個(gè)必要,線程間本來就已經(jīng)共享了同一進(jìn)程內(nèi)的一塊內(nèi)存
如果用戶傳遞的信息較少或是需要通過信號(hào)來觸發(fā)某些行為.前文提到的軟中斷信號(hào)機(jī)制不失為一種簡(jiǎn)捷有效的進(jìn)程間通信方式.
但若是進(jìn)程間要求傳遞的信息量比較大或者進(jìn)程間存在交換數(shù)據(jù)的要求,那就需要考慮別的通信方式了。
無名管道簡(jiǎn)單方便.但局限于單向通信的工作方式.并且只能在創(chuàng)建它的進(jìn)程及其子孫進(jìn)程之間實(shí)現(xiàn)管道的共享:
有名管道雖然可以提供給任意關(guān)系的進(jìn)程使用.但是由于其長(zhǎng)期存在于系統(tǒng)之中,使用不當(dāng)容易出錯(cuò).所以普通用戶一般不建議使用。
消息緩沖可以不再局限于父子進(jìn)程,而允許任意進(jìn)程通過共享消息隊(duì)列來實(shí)現(xiàn)進(jìn)程間通信,并由系統(tǒng)調(diào)用函數(shù)來實(shí)現(xiàn)消息發(fā)送和接收之間的同步,從而使得用戶在使用消息緩沖進(jìn)行通信時(shí)不再需要考慮同步問題,使用方便,但是信息的復(fù)制需要額外消耗CPU的時(shí)間,不適宜于信息量大或操作頻繁的場(chǎng)合。
共享內(nèi)存針對(duì)消息緩沖的缺點(diǎn)改而利用內(nèi)存緩沖區(qū)直接交換信息,無須復(fù)制,快捷、信息量大是其優(yōu)點(diǎn)。
但是共享內(nèi)存的通信方式是通過將共享的內(nèi)存緩沖區(qū)直接附加到進(jìn)程的虛擬地址空間中來實(shí)現(xiàn)的,因此,這些進(jìn)程之間的讀寫操作的同步問題操作系統(tǒng)無法實(shí)現(xiàn)。必須由各進(jìn)程利用其他同步工具解決。另外,由于內(nèi)存實(shí)體存在于計(jì)算機(jī)系統(tǒng)中,所以只能由處于同一個(gè)計(jì)算機(jī)系統(tǒng)中的諸進(jìn)程共享。不方便網(wǎng)絡(luò)通信。
共享內(nèi)存塊提供了在任意數(shù)量的進(jìn)程之間進(jìn)行高效雙向通信的機(jī)制。每個(gè)使用者都可以讀取寫入數(shù)據(jù),但是所有程序之間必須達(dá)成并遵守一定的協(xié)議,以防止諸如在讀取信息之前覆寫內(nèi)存空間等競(jìng)爭(zhēng)狀態(tài)的出現(xiàn)。
不幸的是,Linux無法嚴(yán)格保證提供對(duì)共享內(nèi)存塊的獨(dú)占訪問,甚至是在您通過使用IPC_PRIVATE創(chuàng)建新的共享內(nèi)存塊的時(shí)候也不能保證訪問的獨(dú)占性。 同時(shí),多個(gè)使用共享內(nèi)存塊的進(jìn)程之間必須協(xié)調(diào)使用同一個(gè)鍵值。
?
評(píng)論