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信号,默认动作是进程终止)