程序間通訊本質上讓不同的程序擁有乙份公共的資源。管道則是程序間通訊的一種,分為匿名管道和命名管道。
管道特點:
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 只能在具有公共祖先的程序之間使用。乙個管道由乙個程序建立,然後該...