管道是Linux支持的最初Unix IPC形式之一,具备如下特色: html
管道的实现机制:linux
管道是由内核管理的一个缓冲区,至关于咱们放入内存中的一个纸条。管道的一端链接一个进程的输出。这个进程会向管道中放入信息。管道的另外一端链接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不须要很大,它被设计成为环形的数据结构,以便管道能够被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另外一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另外一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。数组
包含头文件<unistd.h> 数据结构
功能:建立一无名管道 函数
原型: spa
int pipe(int fd[2]); 设计
参数: 3d
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端 code
返回值:成功返回0,失败返回错误代码 htm
man帮助说明:
pipe() creates a pipe, a unidirectional data channel that can be used for interprocess communication. The array pipefd is used to return two file descriptors referring to the ends of the pipe. pipefd[0] refers to the read end of the pipe. pipefd[1] refers to the write end of the pipe. Data written to the write end of the pipe is buffered by the kernel until it is read from the read end of the pipe. For further details, see pipe(7).
该函数建立的管道的两端处于一个进程中间,在实际应 用中没有太大意义,所以,一个进程在由pipe()建立管道后,通常再fork一个子进程,而后经过管道实现父子进程间的通讯(所以也不难推出,只要两个 进程中存在亲缘关系,这里的亲缘关系指的是具备共同的祖先,均可以采用管道方式来进行通讯)。父子进程间具备相同的文件描述符,且指向同一个管道pipe,其余没有关系的进程不能得到pipe()产生的两个文件描述符,也就不能利用同一个管道进行通讯。
建立管道后示意图:
三,利用管道进行父子进程间数据传输
示例一:子进程向管道中写数据,父进程从管道中读出数据
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> int main(void) { int fds[2]; if(pipe(fds) == -1){ perror("pipe error"); exit(EXIT_FAILURE); } pid_t pid; pid = fork(); if(pid == -1){ perror("fork error"); exit(EXIT_FAILURE); } if(pid == 0){ close(fds[0]);//子进程关闭读端 write(fds[1],"hello",5); exit(EXIT_SUCCESS); } close(fds[1]);//父进程关闭写端 char buf[10] = {0}; read(fds[0],buf,10); printf("receive datas = %s\n",buf); return 0; }
结果:
示例二:利用管道实现ls |wc –w功能
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> int main(void) { int fds[2]; if(pipe(fds) == -1){ perror("pipe error"); exit(EXIT_FAILURE); } pid_t pid; pid = fork(); if(pid == -1){ perror("fork error"); exit(EXIT_FAILURE); } if(pid == 0){ dup2(fds[1],STDOUT_FILENO);//复制文件描述符且指定新复制的fd为标准输出 close(fds[0]);//子进程关闭读端 close(fds[1]); execlp("ls","ls",NULL); fprintf(stderr,"exec error\n"); exit(EXIT_FAILURE); } dup2(fds[0],STDIN_FILENO); close(fds[1]);//父进程关闭写端 close(fds[0]); execlp("wc","wc","-w",NULL); fprintf(stderr, "error execute wc\n"); exit(EXIT_FAILURE); }
结果: