程序間通訊 管道

2021-08-03 03:09:05 字數 2868 閱讀 9048

程序間通訊本質上讓不同的程序擁有乙份公共的資源。管道則是程序間通訊的一種,分為匿名管道和命名管道。

管道特點:

1.管道只能用於單向通訊。

2.匿名只能用於有血緣關係之間的通訊,命名管道也能用於無血緣關係之間的通訊 。

3.面向資料流通訊。

4.管道的生命週期隨程序。程序退出,管道也隨之釋放。

5.管道訪問資源時按順序訪問,父子程序同步。

管道其實是一種最基本的ipc機制,由pipe函式建立:int pipe(int filedes[2]);

呼叫pipe函式時在核心中開闢一塊緩衝區(稱為管道)用於通訊,它有乙個讀端乙個寫端,然後通過filedes引數傳出給使用者程式兩個檔案描述符,filedes[0]指向管道的讀端,filedes[1]指向管道的寫端。所以管道在使用者程式看起來就像乙個開啟的檔案,通過read(filedes[0]);或者write(filedes[1]);向這個檔案讀寫資料其實是在讀寫核心緩衝區。pipe函式呼叫成功返回0,呼叫失敗返回-1。

管道實現程序間通訊步驟:

1.父程序呼叫pipe開闢管道,得到兩個檔案描述符指向管道的兩端。

2.父程序呼叫fork建立子程序,那麼子程序也有兩個檔案描述符指向同一管道。

3.父程序關閉管道讀端,子程序關閉管道寫端。父程序可以往管道裡寫,子程序可以從管道裡讀,管道是用環形佇列實現的,資料從寫端流入從讀端流出,這樣就實現了程序間通訊。

下面來看**:

#include#include#include#includeint main()

pid_t id=fork();

if(id<0)else if(id==0)

}else

} return 0;

}

執行結果如下:

但使用管道有一些限制:

兩個程序通過乙個管道只能實現單向通訊。管道的讀寫端通過開啟的檔案描述符來傳遞,因此要通訊的兩個程序必須從它們的公共祖先那裡繼承檔案描述符。上面是父程序把檔案描述符傳給子程序之後父子程序之間通訊,也可以父程序fork兩次,把檔案描述符傳給兩個子程序,然後兩個子程序之間通訊,總之需要通過fork傳遞檔案描述符使兩個程序都能訪問同一管道,它們才能通訊。

如果所有指向管道寫端的檔案描述符都關閉了(管道寫端的引用計數等於0),而仍然有程序從管道的讀端讀資料,那麼管道中剩餘的資料都被讀取後,再次read會返回0,就像讀到檔案末尾一樣。

如果有指向管道寫端的檔案描述符沒關閉(管道寫端的引用計數大於0),而持有管道寫端的程序也沒有向管道中寫資料,這時有程序從管道讀端讀資料,那麼管道中剩餘的資料都被讀取後,再次read會阻塞,直到管道中有資料可讀了才讀取資料並返回。

如果所有指向管道讀端的檔案描述符都關閉了(管道讀端的引用計數等於0),這時有程序向管道的寫端write,那麼該程序會收到訊號sigpipe,通常會導致程序異常終止。

如果有指向管道讀端的檔案描述符沒關閉(管道讀端的引用計數大於0),而持有管道讀端的程序也沒有從管道中讀資料,這時有程序向管道寫端寫資料,那麼在管道被寫滿時再次write會阻塞,直到管道中有空位置了才寫入資料並返回。

管道大小:

管道容量分為pipe buf和pipe capacity兩種。

第一種pipe buf定義的是核心管道緩衝區的容量,這個值是由核心來設定的。可以通過ulimit -a命令檢視。

管道的容量為:sizeof(pipe_buf) = 512bytes * 8 = 4kb

第二種pipe capacity由下面的程式來測試大小。

#include#include#include#includeint main()

; size_t ret=pipe(_pipe);

if(ret==-1)

int count=0;

int id=fork();

if(id==0)

}else

} return 0;

}

子程序關閉讀端一直寫,父程序不讀,寫滿之後,子程序阻塞式等待父程序讀取管道內的資料。

管道的大小為65536個位元組。

命名管道:

命名管道是以fifo的檔案形式儲存於檔案系統中,命名管道是乙個裝置檔案,因此,即使程序與建立fifo的程序不存在親緣關係,只要可以訪問該路徑,就能夠通過fifo相互通訊。fifo總是按照先進先出的原則工作,第乙個被寫入的資料將首先從管道中讀出。

建立命名管道的系統函式有兩個:mknod和mkfifo。

int mknod(const char* path,mode_t mod,dev_t dev)

int mkfifo(const char* path,mode_t mod);

函式mknod引數中path為建立的命名管道的全路徑名,mod為建立的命名管道的模式,指明其訪問的許可權;dev為裝置值,該值取決於檔案建立的種類,它只在建立裝置檔案時才會用到。函式呼叫成功都返回0,失敗都返回1。

命名管道建立後就可以使用了,命名管道和管道的使用方法基本是相同的。只是使用命名管道時,必須先呼叫open()將其開啟。因為命名管道是乙個存在於硬碟上的檔案,而管道是存在於記憶體中的特殊檔案。

呼叫open()開啟命名管道的程序可能會被阻塞。但如果同時用讀寫方式(o_rdwr)開啟,則一定不會導致阻塞;如果以唯讀方式(o_rdonly)開啟,則呼叫open()函式的程序將會被阻塞直到有寫方式開啟管道;同樣以寫方式(o_wronly)開啟也會阻塞直到有讀方式開啟管道。

程序間通訊 管道

include int pipe int fd 2 返回值 若成功,返回0,若出錯,返回 1經由引數fd返回兩個檔案描述符 fd 0 為讀而開啟,fd 1 為寫而開啟。fd 1 的輸出是fd 0 的輸入。else if pid 0 子程序 else else if pid 0 父程序 printf ...

程序間通訊 管道

原文 程序間通訊 管道 管道簡介 常說的管道都是匿名半雙工管道,匿名半雙工管道在系統中是沒有實名的,並不可以在檔案系統中以任何方式看到該管道。它只是程序的一種資源,會隨著程序的結束而被系統清除。管道通訊是在unix系統中應用比較頻繁的一種方式,例如使用grep查詢 ls grep ipc 顧名思義,...

程序間通訊 管道

程序間通訊,又稱為ipc,包含以下型別 半雙工管道fifo 全雙工管道 訊息佇列 訊號 訊號量共享記憶體 套接字socket streams。一,管道是unix系統ipc的最古老形式,他具有兩種侷限性 1 資料只能在乙個方向上流動 2 只能在具有公共祖先的程序之間使用。乙個管道由乙個程序建立,然後該...