#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