1. 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
2. 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
3. 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中;
4. 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <errno.h> int main() { int pipe_fd[2]; pid_t pid; char r_buf[100]; char w_buf[4]; char * p_wbuf; int r_num; int cmd; memset(r_buf, 0, sizeof(r_buf)); memset(w_buf, 0, sizeof(r_buf)); p_wbuf = w_buf; if (pipe(pipe_fd) < 0) { printf("pipe create error\n"); return -1; } if ((pid = fork()) == 0) { close(pipe_fd[1]); sleep(3); /* 确保父进程关闭写端 */ r_num = read(pipe_fd[0], r_buf, 100); printf( "read num is %d the data read from the pipe is %d\n", r_num, atoi(r_buf)); close(pipe_fd[0]); exit(0); } else if (pid > 0) { close(pipe_fd[0]); /* read */ strcpy(w_buf, "111"); if (write(pipe_fd[1], w_buf, 4) != -1) printf("parent write over \n"); /* 管道写端关闭后,写入的数据将一直存在,直到读出为止 */ close(pipe_fd[1]); /* write */ printf("parent close fd[1] over\n"); sleep(10); } return 0; }
对管道的写规则的验证1:写端对读端存在的依赖性
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> int main() { int pipe_fd[2]; pid_t pid; char r_buf[4]; char * w_buf; int writenum; int cmd; memset(r_buf, 0, sizeof(r_buf)); if (pipe(pipe_fd) < 0) { printf("pipe create error\n"); return -1; } if ((pid = fork()) == 0) { close(pipe_fd[0]); close(pipe_fd[1]); sleep(10); exit(0); } else if (pid > 0) { sleep(1); /* 等待子进程完成关闭读端的操作 */ close(pipe_fd[0]); /* write */ w_buf = "111"; if ((writenum = write(pipe_fd[1], w_buf , 4)) == -1) printf("write to pipe error\n"); else printf("the bytes write to pipe is %d\n", writenum); close(pipe_fd[1]); } return 0; }
则输出结果为: Broken pipe,原因就是该管道以及它的所有fork()产物的读端都已经被关闭。如果在父进程中保留读端,即在写完pipe后,再关闭父进程的读端,也会正常写入pipe,读者可自己验证一下该结论。因此,在向管道写入数据时,至少应该存在某一个进程,其中管道读端没有被关闭,否则就会出现上述错误(管道断裂,进程收到了SIGPIPE信号,默认动作是进程终止)