程序間的通訊方式 pipe(1 管道)

2021-08-18 21:54:34 字數 3360 閱讀 3210

程序通訊就是兩個程序之間進行資料交換,在linux中有好幾種可以進行程序通訊的方式,在這篇文章中我們主要介紹最基本的程序通訊方式——pipe管道。

程序之間交換資訊的唯一途徑就是傳送開啟的檔案。

管道是一種最古老也是最基本的系統ipc形式,所有的linux系統都提供此種通訊機制。但是管道有以下兩個侷限性:

管道是由核心管理的乙個緩衝區,它的一端連線乙個程序的輸出,另一端連線乙個程序的輸入。管道的緩衝區不需要很大,它被設計為環形的資料結構,當兩個程序都終止後,管道的生命週期也會被結束。

管道是通過呼叫pipe函式建立的。

#include int     pipe(int fd[2]);
它由輸出型引數fd返回兩個檔案描述符,fd[0]為讀而開啟,fd[1]為寫而開啟,fd[1]的輸出是fd[0]的輸入,當管道建立成功後pipe函式返回0,如果建立失敗則返回-1,fd[0]和fd[1]之間的關係如下圖:

上面我們在單個程序中建立了管道,但是實際上,單個程序中的管道是沒有什麼用的,通常,程序會先呼叫pipe函式產生管道,接著呼叫fork()函式,fork函式會將父程序的相關資料結構繼承到子程序中,這樣就使子程序中的檔案描述符表中的fd[0]和fd[1]指向父程序所指向的管道檔案,這樣就能實現兩個程序之間的通訊了。上面的過程如下圖:

對於乙個從子程序到父程序的管道(子程序寫,父程序讀),父程序關閉fd[1],子程序關閉fd[0],當管道的一段被關閉後(在上面的基礎上關閉管道的一端)下列兩條規則起作用:

當讀乙個寫段已經被關閉的管道時,在所有的資料都被讀取後,read返回0(read返回0表示已經讀到檔案結束符);

下面我們進行驗證:

#include#include #include #include #include #include int main()

; if(pipe(fd)!=0)

// pipe create success

pid_t id=fork();

if(id==0)

sleep(1);

printf("child is writing...\n");

}close(fd[1]);

exit(0);

}else

else if(len==0)

else

}close(fd[0]);

int status=0;

pid_t _pid=waitpid(id,&status,0);

if(_pid==id)

else

exit(0);

}return 0;

}

程式讓子程序寫三次字串然後關閉子程序fd[1],即關閉管道的寫端,不關閉父程序的fd[0],即管道的讀端。

如果寫乙個讀端已經被關閉的管道,則會產生相關訊號對寫段的程序進行終止,如果忽略該訊號或捕捉該訊號並從處理程式返回,則write會返回-1,errno會設定為epipe;

下面我們進行驗證:

#include#include #include #include #include #include int main()

; if(pipe(fd)!=0)

// pipe create success

pid_t id=fork();

if(id==0)

printf("child is writing...\n");

}close(fd[1]);

}else

else if(len==0)

else

}close(fd[0]);

int status=0;

pid_t _pid=waitpid(id,&status,0);

if(_pid==id)

else

exit(0);

}return 0;

}

**的意圖是這樣:我們讓write端(子程序)一直寫字串msg,而read端(父程序)先讀三次然後在關閉掉父程序的fd[0],這樣就形成了子程序一直寫,而父程序沒有在讀的情況。結果如下:

我們發現父程序關閉掉fd[0]後子程序被異常終止了,我們從子程序的退出碼和退出信號碼發現它是被13號訊號(sigpipe)所終止的,所以寫乙個讀端關閉的管道這對pipe來說並不成立,作業系統會在讀端關閉後向寫端的程序傳送sigpipe使程序被終止。

如果管道的讀端和寫端都沒有關閉,但是管道的寫端沒有再向管道寫資料了。這時如果管道中沒有資料了,那麼在此read程序會產生阻塞,直到管道中有資料了才讀取資料並返回。

如果有指向管道讀端的檔案描述符沒有關閉,而持有管道讀端的沒有從管道中讀資料,這時有程序向管道中寫資料,如果管道被寫滿再向管道寫資料是,再次write會導致程序阻塞,直到管道中有空間了才會繼續向管道中寫資料並返回。

我們可以通過* man 7 pipe*;來查詢管道的容量pipe_capacity

## linux的管道實現機制

從本質上說,管道也是一種檔案,但它又和一般的檔案有所不同,管道可以克服使用檔案進行通訊的兩個問題,具體表現為:

管道是乙個固定大小的緩衝區,在linux中,該緩衝區的大小為一頁,即4kb,使它的大小不會像普通檔案那樣不加檢驗的增長。在linux中,核心使用struct pipe_inode_info結構體來描述乙個管道,這個結構體定義在pipe_fs_i.h中。

struct pipe_inode_info結構體

struct pipe_inode_info ;
緩衝區的個數

#define pipe_buffers (16)
管理緩衝區的結構

struct pipe_buffer ;

程序間通訊(1) 管道pipe

學習linux的知識中,有乙個特別重要的概念叫 程序 而要進行程序間通訊時,有乙個特別重要的概念就是 管道,今天,我們就來學習一下什麼是管道,它能又幹什麼呢?一 概念 管道 把乙個程序連線到另外乙個程序的乙個資料流稱為管道。其實,我們聯絡現實生活,自來水管可以將我們使用者和供水站連線起來,通過管道運...

程序間的通訊方式 pipe(管道)

每個程序各自有不同的使用者位址空間,任何乙個程序的全域性變數在另乙個程序中都看不到,所以程序之間要交換資料必須通過核心,在核心中開闢一塊緩衝區,程序a把資料從使用者空間拷到核心緩衝區,程序b再從核心緩衝區把資料讀走,核心提供的這種機制稱為程序間通訊。不同程序間的通訊本質 程序之間可以看到乙份公共資源...

1 程序間通訊 PIPE(無名管道)

1 在子程序中寫入資料,在父程序中讀取資料 code 結果 now,write data to the pipe the data i wrote is jason s messag now read data from pipe the data from pipe is jason s mess...