每個程序各自有不同的使用者位址空間,任何乙個程序的全域性變數在另乙個程序中都看不到,所以程序之間交換資料必須通過核心,在核心中開闢一塊緩衝區,程序1把資料從使用者空間拷到核心緩衝區,程序2再從核心緩衝區中把資料讀走,核心提供的這種機制稱為程序間通訊(ipc):
一、管道
管道是一種最基本的ipc機制,由pipe函式建立:
#include int pipe(int filedes[2]);
呼叫pipe函式時在核心中開闢一塊緩衝區(稱為管道)用於通訊,它有乙個讀端乙個寫端,然後通過filedes引數傳出給使用者程式兩個檔案描述符,filedes[0]指向管道的讀端,filedes[1]指向管道的寫端。所以在使用者程式看來就像乙個開啟的檔案,通過read(filedes[0]);或者write(filedes[1]);向這個檔案讀寫資料其實是在讀寫核心緩衝區。pipe函式呼叫成功返回0,呼叫失敗返回-1。
開啟了管道之後可以按如下的步驟通訊:
父程序呼叫pipe開闢管道,得到兩個檔案描述符指向管道的兩端。
父程序呼叫fork建立子程序,那麼子程序也有兩個檔案描述符指向同一管道。
父程序關閉管道讀端,子程序關閉管道寫端。父程序可以往管道裡寫,子程序可以從管道裡讀,管道使用環形佇列實現的,資料從寫端流入從讀端流出,這樣就實現了程序間通訊。
例:
#include #include #define maxline 80
int main(void)
if ((pid = fork()) < 0)
if (pid > 0) else
return 0;
}
使用管道有一些限制:
使用管道需要注意一下4點(假設都是阻塞i/o操作,沒有設定o_nonblock標誌):
如果所有指向管道寫端的檔案描述符都關閉了(管道寫端的引用計數為0),而仍然有程序從管道的讀端讀資料,那麼管道中剩餘的資料都被讀取後,再次read會返回0,就像讀到檔案末尾一樣。
如果有指向管道寫端的檔案描述符沒關閉(管道寫端的引用計數大於0),而持有管道寫端的程序也沒有向管道中寫資料,這時有程序從管道讀資料,那麼管道中剩餘的資料都被讀取後,再次read會阻塞,直到管道中有資料可讀了才讀取資料並返回。
如果所有指向管道讀端的檔案描述符都關閉了(關閉讀端的引用計數等於0),這時有程序向管道的寫端write,那麼該程序會收到訊號sigpipe,通常會導致程序異常終止。
如果有指向管道讀端的檔案描述符沒關閉(管道讀端的引用計數大於0),而持有管道讀端的程序也沒有從管道中讀資料,這時有程序向管道寫端寫資料,那麼在管道被寫滿時再次write會阻塞,直到管道中有了空位置才寫入資料並返回。
二、其他ipc機制
程序間通訊必須通過核心提供了通道,而且必須有一種方法在程序中標示核心提供的某個通道,上一節講的管道是用開啟的檔案描述符來標示的。如果要互相通訊的幾個程序沒有從公共祖先那裡繼承檔案描述符就不能通訊了。核心提供一條通道不是問題,問題是如何標識這條通道才能使各程序都可以訪問它?檔案系統中的路徑名是全域性的,各程序都可以訪問,因此可以用檔案系統中的路徑名來標識乙個ipc通道。
fifo和unix domain socket這兩種ipc機制都是利用檔案系統中的特殊檔案來標識的,可以用mkfifo命令建立乙個fifo檔案:
fifo檔案在磁碟上沒有資料塊,僅用來標識核心中的一條通道,各程序可以開啟這個檔案進行read/write,實際上是在讀寫核心通道(根本原因在於這個file結構體所指向的read、write函式和常規檔案不一樣),這樣就實現了程序間通訊。
socket和fifo的原理類似,也需要乙個特殊的socket檔案來標識核心中的通道,例如/var/run目錄下有很多系統服務的socket檔案,檔案型別s表示socket,這些檔案在磁碟上沒有資料塊。unix domail socket是目前最廣泛使用的ipc機制。
總結一下程序間通訊的機制:
1.父程序通過fork可以將開啟檔案的描述符傳遞給子程序
2.子程序結束時,父程序呼叫wait可以得到子程序的終止資訊
3.幾個程序可以在檔案系統中讀寫某個共享檔案,也可以通過給檔案加鎖來實現程序間同步
4.程序之間互發訊號,一般使用sigusr1和sigusr2實現使用者自定義功能
5.管道
6.fifo
7.mmap函式,幾個程序可以對映同一記憶體區
8.sys v ipc,以前的sys v unix系統實現的ipc機制,包括訊息佇列、訊號量和共享記憶體,現在已經基本廢棄
9.unix domain socket,目前最廣泛使用的ipc機制
php程序間通訊 yoc PHP程序間通訊
php是用c編寫的,因此它對系統底層api的操作與c很像,同大多數語言一樣,php程序間通訊的方式有以下幾種 訊息佇列,管道,共享記憶體,socket和訊號。本文是對這幾種通訊方式對整理 管道通訊pipe 管道用於承載簡稱之間的通訊資料。為了方便理解,可以將管道比作檔案,程序a將資料寫到管道p中,然...
程序間通訊
實現程序間資料共享除了常用的記憶體檔案對映外,對於一些非檔案的資料共享可以直接使用wm copydata。如果需要在程序a傳遞資料到程序b,簡單的實現如下 在程序a中 cstring strdatatosend t hello 需要傳遞的資料 hwnd hwndreceived 程序b的接收資料視窗...
程序間通訊
最近做專案遇到奇怪的問題,我在主線程中建立乙個工作執行緒。在工作執行緒中用sendmessage向主線程傳送訊息,通知主線程操作office 物件。getactiveobject時提示 hr 0x8001010d 因為應用程式正在傳送乙個輸入同步呼叫,所以無法執行傳出的呼叫。我把sendmessag...