无名管道
是相对于有名管道而言的,无名管道在使用时产生,不使用后释放,并不会再系统上留下任何蛛丝马迹。
无名管道因其使用前没有任何的标示,所以它只能应用于父子进程之间。
子进程会复制父进程的文件表数组(浅拷贝)。
无名管道的相关操作:
创建:int pipe(int fd[2]); //fd[0] 读 //fd[1] 写
pipe 函数的参数是一个由两个整数类型的文件描述符组成的数组的指针,要注意这里使用的是文件描述符而不是文件流所以我们必须使用底层的 read 和 write 调用来访
问数据,而不是用文件流库函数 fread 和 fwrite。
打开:同上
读操作:read(fd[0], buffer, size);
写操作:write(fd[1], buffer, len);
关闭:close(fd[1]); close(fd[0]);
注意:管道都是半双工通信,而无名管道创建后,父进程在 fork 产生子进程后,两个进程分别有一对读写权限,所以要在父子进程中分别关闭读或写。
练习:父进程从用户端循环读入数据,子进程输出字符串并统计字符串的长度。
代码如下:
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <unistd.h> #include <string.h> #include <fcntl.h> int main() { int fd[2]; pid_t pid; int p = pipe(fd); if (p == 0) { printf("pipe success\n"); } else { printf("pipe fail\n"); } pid = fork(); assert(pid != -1); if (pid == -1) { exit(0); } if (pid == 0) { close(fd[1]); char buffer2[128] = {0}; while (read(fd[0],buffer2,127) > 0) { printf("%s\n", buffer2); printf("num = %d\n", strlen(buffer2)); } } else { close(fd[0]); char buffer1[128] = {0}; printf("Please input: "); while (strncmp(buffer1,"end",3) != 0) { fgets(buffer1, 128, stdin); write(fd[1], buffer1, strlen(buffer1)-1); memset(buffer1, 0, 128); } } return 0; }
测试运行结果如下图所示: