Linux程序間通訊之管道

2021-07-27 18:38:54 字數 3679 閱讀 8721

管道,你可以把它想成一根資料線,連線了兩個程序,使他們可以互相通訊。更嚴謹來說,它是乙個檔案或者一塊共享區,乙個程序往裡面寫資料,另乙個程序從裡面拿資料,以此種方式完成程序間通訊。

管道是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最古老的形式。其本質是乙個偽檔案 實為核心緩衝區 它是半雙工的 即資料只能在乙個方向上流動 具有固定的讀端和寫端。它只能用於具有親緣關係的程序之間的通訊 也是父子程序或者兄弟程序之間 它可以看成是一種特殊的檔案,對於它的讀寫也可以使用普通的...