管道是一種兩個進程間進行單向通信的機制。因為管道傳遞數據的單向性,管道又稱為半雙工管道。管道的這一特點決定了器使用的局限性。管道是Linux支持的最初Unix IPC形式之一,具有以下特點:
????? 數據只能由一個進程流向另一個進程(其中一個讀管道,一個寫管道);如果要進行雙工通信,需要建 立兩個管道。
????? 管道只能用于父子進程或者兄弟進程間通信。,也就是說管道只能用于具有親緣關系的進程間通信。
除了以上局限性,管道還有其他一些不足,如管道沒有名字(匿名管道),管道的緩沖區大小是受限制的。管道所傳輸的是無格式的字節流。這就需要管道輸入方和輸出方事先約定好數據格式。雖然有那么多不足,但對于一些簡單的進程間通信,管道還是完全可以勝任的。
使用管道進行通信時,兩端的進程向管道讀寫數據是通過創建管道時,系統設置的文件描述符進行的。從本質上說,管道也是一種文件,但它又和一般的文件有所不同,可以克服使用文件進行通信的兩個問題,這個文件只存在內存中。
通過管道通信的兩個進程,一個進程向管道寫數據,另外一個從中讀數據。寫入的數據每次都添加到管道緩沖區的末尾,讀數據的時候都是從緩沖區的頭部讀出數據的。
#include
int pipe(int pipefd[2]);
(匿名)管道兩端分別用描述符pipefd[0]及pipefd[1]來描述。需要注意的是,管道兩端的任務是固定的,一端只能用于讀,有描述符pipefd[0]表示,稱其為管道讀端;另一端只能用于寫,由描述符pipe[1]來表示,稱其為管道寫端。該函數創建的管道的兩端處于一個進程中間,在實際應用中沒有太大意義,因此,一個進程在由pipe()創建管道后,一般再fork一個子進程,然后通過管道實現父子進程間的通信。
1. 函數說明
pipe(建立管道):
1) 頭文件 #include
2) 定義函數: int pipe(int filedes[2]);
3) 函數說明: pipe()會建立管道,并將文件描述詞由參數filedes數組返回。
filedes[0]為管道里的讀取端
filedes[1]則為管道的寫入端。
4) 返回值:? 若成功則返回零,否則返回-1,錯誤原因存于errno中。
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int filedes[2];
charbuf[80];
pid_t?pid;
pipe(?filedes?);
pid=fork();
if(pid?>?0)
{
printf("This?is?in?the?father?process,here?write?a?string?to?the?pipe.\n");
chars[]?="Hello?world?,?this?is?write?by?pipe.\n";
write(?filedes[1],?s,sizeof(s)?);
close(?filedes[0]?);
close(?filedes[1]?);
}
elseif(pid?==?0)
{
printf("This?is?in?the?child?process,here?read?a?string?from?the?pipe.\n");
read(?filedes[0],?buf,sizeof(buf)?);
printf("%s\n",?buf?);
close(?filedes[0]?);
close(?filedes[1]?);
}
waitpid(?pid,?NULL,?0?);
return0;
}
運行結果:
[root@localhost src]# gcc pipe.c
[root@localhost src]# ./a.out
This is in the child process,here read a string from the pipe.
This is in the father process,here write a string to the pipe.
Hello world , this is write by pipe.
當管道中的數據被讀取后,管道為空。一個隨后的read()調用將默認的被阻塞,等待某些數據寫入。