管道,你可以把它想成一根資料線,連線了兩個程序,使他們可以互相通訊。更嚴謹來說,它是乙個檔案或者一塊共享區,乙個程序往裡面寫資料,另乙個程序從裡面拿資料,以此種方式完成程序間通訊。
管道是unix系統ipc最古老的形式,所有的unix系統都提供此種通訊機制(unix系統ipc是各種程序通訊方式的統稱)。
管道在進行通訊時,基於位元組流。
管道可分為兩類:
匿名管道是通過呼叫函式pipe建立的:
#include
int pipe(int fd[2]);
返回值:成功返回0,失敗返回-1。
該函式會經過引數fd返回兩個檔案描述符fd[0]和fd[1]。我們可以理解為fd[0]是為了從管道中讀資料而開啟的;fd[1]是為了向管道中寫資料而開啟的。所以管道在使用者程式看了像是開啟了乙個檔案。向這個檔案讀寫資料其實就是在讀寫核心緩衝區。
呼叫完函式後,系統會將當前程序的輸入輸出(即返回的兩個檔案描述符fd[0]和fd[1])分別連線到管道的讀端與寫段。如圖:
檔案描述符資訊是記錄在pcb當中的,當我們想讓兩個程序通訊時就可以令當前程序fork子程序,讓子程序繼承父程序的pcb資訊。這樣子程序的fd[0]和fd[1]也是連線到這個管道的。
這也是為什麼匿名管道限制了只有具有血緣關係的程序才能通訊。沒有血緣關係的是不可能連線到乙個管道的。
這裡再說明匿名管道的乙個特性,它只支援單向通訊(半雙工通訊),也就是說同一時刻只能有乙個人在發乙個人在收。所以父程序與子程序額讀端與寫端不能全部開啟。同時只能乙個程序開啟讀端另乙個程序開啟寫端,另外的埠全部關閉。
我們下面用父程序開啟寫段,子程序開啟讀段繼續講解。(因為所有埠預設都是開啟的,所以我們需要呼叫close函式將其關閉)
這樣我們就構成了乙個由父程序到子程序的管道。父程序負責寫,子程序負責讀。
向管道讀寫資料類似於向檔案讀寫資料,呼叫write和read函式就可實現。
#include
#include
#include
#include
int main()
pid_t id = fork();//建立子程序
if(id < 0)
else
if(id == 0)
}else
wait();
}return
0;}
匿名管道有以下四種情況需要注意:
fifo被成為匿名管道,上面說的匿名管道只能完成有血緣關係的兩個程序間的通訊,這兩個程序要有公共祖先。而命名管道fifo可以讓不相關的兩個程序也通訊。
命名管道不同於pipe之處在於命名管道是乙個裝置檔案,它真真在在的存在於硬碟之上,存在於檔案系統中。而匿名管道存在於記憶體或者核心中,它對檔案系統不可見。也正因為如此,命名管道可以完成任意兩個程序間的通訊。
命名管道的建立有乙個路徑名path與之關聯,以fifo檔案的形式儲存在檔案系統中,所以只要可以訪問該路徑,就能夠通過fifo互相通訊。
注意:fifo是按照先入先出的規則進行資料讀寫,第乙個被寫入的也將最先被讀出。
命名管道的建立方式有兩種,是
#include
#include
int mknod(const
char* path,mode_t mod,dev_t dev)
函式mknod的引數path即為建立的命名管道的全路徑名(包括管道檔案的檔名),如」/home/tmp/fifo」。第二個引數mod為建立命名管道的模式(一般為s_ififo|0666,0666表示管道ipc的預設許可權)。dev為裝置值,取決於檔案建立的種類,它只在建立裝置檔案時才會用到。
返回值:成功返回0,失敗返回-1。
#include
#include
int mkfifo(const
char* path,mode_t mode)
此函的的兩個引數與上相同,返回值也相同,成功返回0,失敗返回-1。
mknod是比較老的函式,mkfifo函式更加的簡單規範,所以建議盡量使用mkfifo。
當我們建立好管道之後並不能直接使用它,使用之前必須呼叫open函式將其開啟,並獲取檔案描述符。
#include
#include
#include
int open(const
char *pathname, int flags);
引數pathname即為我們要開啟的管道檔案,引數flags為開啟方式,一般有以唯讀方式開啟o_rdonly 或以只寫方式開啟o_wronly。
open函式的返回值為乙個檔案描述符,我們通過這個檔案描述符對管道進行讀寫操作。
傳送端**:
#include
#include
#include
#include
#include
#include
#define _path_ "/home/lzk/test/11_class_2_14/fifo/namefifo"
int main()
int fd = open(_path_,o_wronly);//開啟管道並獲取檔案描述符
if(fd < 0 )
char send_buf[100];
memset(send_buf,'\0',sizeof(send_buf));
while(1)
close(fd);//關閉檔案描述符
printf("hello geter\n");
return
0;}
接受端**:
#include
#include
#include
#include
#define _path_ "/home/lzk/test/11_class_2_14/fifo/namefifo"
int main()
char* get_buf[100];
while(1)
close(fd);//關閉檔案描述符
return
0;}
檔案系統中的路徑名是全域性的,各個程序都可以訪問,因此可以用檔案系統的路徑名來標識乙個ipc通道。
命名管道fifo是乙個特殊的裝置檔案,它在檔案系統中真實存在。
命名管道與匿名管道的使用方法是一致的,只是命名管道在使用前要呼叫open函式開啟。因為命名管道是存在於硬碟上的真實檔案,而匿名管道是存在與記憶體中的特殊檔案。
命名管道開啟方式的不同也可能引起阻塞。如果同時以讀寫方式開啟,則一定不會阻塞;若單單以讀方式開啟,則呼叫open函式的程序會一直阻塞到有寫方式開啟;同樣,單單以寫方式開啟的程序會一直阻塞到有讀方式開啟。當然在阻塞時我們可以異常終止程式。
linux程序間通訊之管道通訊
一 命名管道通訊 管道通訊分為 無名管道和有名管道 無名管道是用於父子孫程序,之間有血緣關係 有名管道 用於任意兩個程序 無名管道 1 建立 int pipe int filedis 2 它會建立兩個檔案描述符 filedis 0 用於讀管道 filedis 1 用於寫管道 通常先建立乙個管道,再通...
linux程序間通訊之管道
下面幾節,將分別溫習下linux程序進通訊的幾種機制1 管道 管道是比較古老的程序間的通訊方式。主要有有名管道和無名管道兩種。2 無名管道 它的特點就是 1 只能使用在具有親緣關係的程序之間的通訊 父子程序或者兄弟程序之間 因為只有具有親緣關係的程序才能繼承其建立的檔案描述符。2 是乙個半雙工的通訊...
Linux 程序間通訊之管道
這裡說的管道是指匿名管道 無名管道 是 unix 系統ipc最古老的形式。其本質是乙個偽檔案 實為核心緩衝區 它是半雙工的 即資料只能在乙個方向上流動 具有固定的讀端和寫端。它只能用於具有親緣關係的程序之間的通訊 也是父子程序或者兄弟程序之間 它可以看成是一種特殊的檔案,對於它的讀寫也可以使用普通的...