linux中pipe

調用pipe函數時在內核中開闢一塊緩衝區(稱爲管道)用於通信,它有一個讀端一個寫端,然後通過filedes參數傳出給用戶程序兩個文件描述符,filedes[0]指向管道的讀端,filedes[1]指向管道的寫端(很好記就像0是標準輸入1是標準輸出一樣)。所以管道在用戶程序看起來就像一個打開的文read(filedes[0]);或者write(filedes[1]);向這個文件讀寫數據其實是在讀寫內核緩衝區。 pipe函數調用成功返回0,調用失敗返回-1。 開闢了管道之後如何實現兩個進程間的通信呢?可以按下面的步驟通信。

1. 父進程調用pipe開闢管道,得到兩個文件描述符指向管道的兩端。
2. 父進程調用fork創建子進程,那麼子進程也有兩個文件描述符指向同一管道。

3. 父進程關閉管道讀端,子進程關閉管道寫端。父進程可以往管道里寫,子進程可以從管道里,管道是以環形隊列實現的,數據從寫端流入從讀端流出,這樣就實現了進程間通信。

wKioL1en5yGCam-5AAD9lQZwY-s780.png

wKiom1en5z6BtWAzAAHHlz5E-ig645.png

wKiom1en52KxwIlfAAG7vz_fQ1w442.png

代碼如下:

#include<stdio.h>

#include<unistd.h>

#include<errno.h>

#include<string.h>

int main()

{

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會阻塞,直到管道中有空位置了才寫數據並返回。

有興趣的童鞋可以驗證一下!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章