#include<unistd.h>
int pipe(int filedes[2]);//return 0 on success,or -1 on error
複製代碼
filedes[0]表示管道的讀取端;shell
filedes[1]表示管道的寫入端;bash
使用read()和write()系統調用來在管道上執行I/O。函數
read()會堵塞直到全部管道的寫入描述符關閉爲止。大數據
當一個進程試圖向管道中寫入數據但沒有任何進程擁有該管道的打開着的讀取描述符的時候,內核會向寫入進程發送一個SIGPIPE信號(默認會殺死進程),進程能夠捕獲或忽略該信號,這樣write操做將會返回EPIPE的錯誤。收到SIGPIPE信號或獲得EPIPE錯誤能夠獲知管道的狀態,能夠避免寫入被堵塞的風險,由於一直寫入數據沒有讀取,將會充滿管道,那麼後續的寫入請求都將會被堵塞。ui
當全部進程中的管道文件描述符都關閉以後纔會銷燬該管道以及釋放該管道佔用的資源以供其餘進程複用。同時,管道中的數據都會丟失。spa
父進程在建立子進程以前構建了一個管道。每一個子進程會繼承管道的寫入端的文件描述符並完成動做以後關閉這些描述符。當全部子進程都關閉了管道的寫入端的文件描述符以後,父進程在管道上的read()就會結束並返回文件結束(0)。這時,父進程就可以作其餘工做了。(父進程要關閉管道的寫入端,不然將永遠阻塞。)code
switch (fork()) {
case -1:
ERR_EXIT("fork");
case 0:
if (close(pfd[0]) == -1)
ERR_EXIT("close");
//Child does some work,and lets parent know It‘s done
if(close(pfd[1])==-1)
ERR_EXIT("close");
//child now carries on to do other things...
_exit(EXIT_SUCCESS);
default:
break;
}
if(close(pfd[1])==-1)
ERR_EXIT("close");
//parent may do other work,then synchronizes with children
if(read(pfd[0],&dummy,1)!=0)//block
ERR_EXIT("read");
複製代碼
#include<stdio.h>
FIFE *popen(const char *command,const char *mode);
//return file stream,or NULL on error
int pclose(FILE *stream);
//return termination status of child process,or -1 on error
複製代碼
popen() 函數建立了一個管道,而後建立了一個子進程來執行shell,而shell又建立了一個子進程來執行command字符串。mode參數是一個字符串,它確調用進程是從管道中讀取數據(mode是r)仍是將數據寫入到管道中(mode是w)。cdn
mode的取值肯定了所執行的命令的標準輸出是鏈接到管道的寫入端仍是將其標準輸入鏈接到管道的讀取端。blog
調用進程fp--(fork(),exec())-->/bin/sh--(fork(),exec())-->命令(stdout)--(管道)-->調用進程fp繼承
a)mode is r
調用進程fp--(fork(),exec())-->/bin/sh--(fork(),exec())-->命令(stdin)
調用進程fp--(管道)-->命令stdin
b) mode is w