調用pipe函數時在內核中開闢一塊緩衝區(稱爲管道)用於通訊,它有一個讀端一個寫端,而後經過filedes參數傳出給用戶程序兩個文件描述符,filedes[0]指向管道的讀端,filedes[1]指向管道的寫端(很好記就像0是標準輸入1是標準輸出同樣)。因此管道在用戶程序看起來就像一個打開的文通read(filedes[0]);或者write(filedes[1]);向這個文件讀寫數據實際上是在讀寫內核緩衝區。 pipe函數調用成功返回0,調用失敗返回-1。 開闢了管道以後如何實現兩個進程間的通訊呢?能夠按下面的步驟通訊。
ide
1. 父進程調用pipe開闢管道,獲得兩個文件描述符指向管道的兩端。
2. 父進程調用fork建立子進程,那麼子進程也有兩個文件描述符指向同一管道。
函數
3. 父進程關閉管道讀端,子進程關閉管道寫端。父進程能夠往管道里寫,子進程能夠從管道里讀,管道是以環形隊列實現的,數據從寫端流入從讀端流出,這樣就實現了進程間通訊。
spa
代碼以下:
code
#include<stdio.h>orm
#include<unistd.h>blog
#include<errno.h>隊列
#include<string.h>進程
int main()ip
{get
int pipe_fd[2]; //讀、寫
if(pipe(pipe_fd)<0)
{
printf("pipe error:%d",strerror(errno));
return 1;
}
pid_t id=fork();//建立管道
if(id==0)//child
{//write
close(pipe_fd[0]); //關掉讀端
char*str="hello bit\n";
int count=0;
while(1)
//while(count<5)
{
write(pipe_fd[1],str,strlen(str));
count++;
sleep(1);
// printf("write success:%d\n",count++);
}
close(pipe_fd[1]);
sleep(20);
}
else
{//read
close(pipe_fd[1]); //關掉寫端
char buf[1024];
//while(1)
int count=0;
while(count++<5)
{
//sleep(5);
buf[0]='\0';
ssize_t sz=read(pipe_fd[0],buf,sizeof(buf)-1);
if(sz>0)
{
buf[sz]='\0';
printf("father msg from child:%s\n",buf);
}
}
close(pipe_fd[0]);
sleep(20);
int status=0;
pid_t ret=waitpid(id,&status,0);
if(ret==id)
{
printf("wait sucess,get sig:%d\n,exit code:%d\n",status & 0xff,(status>>8) & 0xff); //低八位是退出信息,次低八位是退出碼(進程的退出碼範圍是0-255)
}
}
}
1. 若是全部指向管道寫端的文件描述符都關閉了(管道寫端的引用計數等於0),但仍然有進程從管道的讀端讀數據,那麼管道中剩餘的數據都被讀取後,再次read會返回0,就像讀到文件末尾同樣;
2. 若是有指向管道寫端的文件描述符沒關閉(管道寫端的引用計數大於0),但持有管道寫端的進程也沒有向管道中寫數據,這時有進程從管道讀端讀數據,那麼管道中剩餘的數據都被讀取後,再次read會阻塞,直到管道中有數據可讀了纔讀取數據並返回。
3. 若是全部指向管道讀端的文件描述符都關閉了(管道讀端的引用計數等於0),這時有進程向管道的寫端write,那麼該進程會收到信號SIGPIPE,一般會致使進程異常終止。
4. 若是有指向管道讀端的文件描述符沒關閉(管道讀端的引用計數大於0),但持有管道讀端的進程也沒有從管道中讀數據,這時有進程向管道寫端寫數據,那麼在管道被寫滿時再 次write會阻塞,直到管道中有空位置了才寫數據並返回。
有興趣的童鞋能夠驗證一下!