Pipe笔记
 Pipe笔记 
 2 管道(匿名)
2.1 管道的概念
- 本质:- 内核缓冲区
- 伪文件-不占用磁盘空间
 
- 特点:- 两部分:- 读端,写端,对应两个文件描述符
- 数据写端流入,读端流出
 
- 操作管道的进程被销毁之后,管道自动被释放
- 管道默认是阻塞的- 读写
 
 
- 两部分:
2.2 管道的原理
- 内部实现方式:队列- 环形队列
- 特点:先进先出
 
- 缓冲区大小:- 默认4K
- 大小会根据实际情况做适当调整
 
2.3 管道的局限性
- 队列- 数据只能读取一次,不能重复读取
 
- 半双工:- 单工:遥控器
- 半双工:对讲机- 数据传输的方向是单向的
 
- 双工:电话
 
- 匿名管道:- 适用于有血缘关系的进程
 
2.4 创建匿名管道
- int pipe(int fd[2]);- fd - 传出参数
- fd[0] - 读端(=3, 因为stdin=0, stdout=1, stderr=2)
- fd[1] - 写端(=4)
 
2.5 父子进程使用管道通信
- 思考:- 单个进程能否使用管道完成读写操作?- 可以
 
- 父子进程间通信是否需要sleep函数?- 否
 
 
- 单个进程能否使用管道完成读写操作?
- 注意事项:- 父进程读时:关闭写端
- 子进程写时:关闭读端
 
- 练习- 父子进程间通信,实现ps aux | grep bash- 数据重定向:dup2
- execlp
 代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 /* 程序来源:https://www.bilibili.com/video/av17360025/?p=30 * 程序功能:父子进程间通信,实现`ps aux | grep bash` */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> int main() { int fd[2]; if(pipe(fd)){ perror("pipe error"); exit(EXIT_FAILURE); } pid_t pid=fork(); if(pid == -1){ perror("fork error"); exit(EXIT_FAILURE); } //父进程: `ps aux` if(pid > 0){ // 写管道的操作,关闭读端 close(fd[0]); // 文件描述符重定向:STDOUT_FILENO->管道写端 dup2(fd[1], STDOUT_FILENO); execlp("ps", "ps", "aux", NULL); perror("execlp"); exit(EXIT_FAILURE); } //子进程: `grep --color=auto bash` else if(pid == 0){ close(fd[1]); dup2(fd[0], STDIN_FILENO); execlp("grep", "grep", "--color=auto", "bash", NULL); perror("execlp"); exit(EXIT_FAILURE); } return 0; } 
- 兄弟进程间通信,实现 - ps aux | grep bash。代码如下:- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 - /* 程序来源:https://www.bilibili.com/video/av17360025/?p=30 * 程序功能:兄弟进程间通信,实现`ps aux | grep bash` */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <wait.h> int main() { int fd[2]; if(pipe(fd)){ perror("pipe error"); exit(EXIT_FAILURE); } int i; pid_t pid[2]; for(i=0; i<2; i++){ pid[i]=fork(); if(pid[i] == -1){ perror("fork error"); exit(EXIT_FAILURE); } else if(pid[i] == 0) break; } //子进程1: `ps aux` if(i==0){ // 写管道的操作,关闭读端 close(fd[0]); // 文件描述符重定向:STDOUT_FILENO->管道写端 dup2(fd[1], STDOUT_FILENO); execlp("ps", "ps", "aux", NULL); perror("execlp"); exit(EXIT_FAILURE); } //子进程2: `grep --color=auto bash` else if(i == 1){ close(fd[1]); dup2(fd[0], STDIN_FILENO); execlp("grep", "grep", "--color=auto", "bash", NULL); perror("execlp"); exit(EXIT_FAILURE); } else if(i==2){ close(fd[0]); close(fd[1]); pid_t wpid; while((wpid=waitpid(-1, NULL, WNOHANG))!=-1){ if(wpid==0){ continue; } printf("waitpid: %lu\n", wpid); } } return 0; } 
 
- 父子进程间通信,实现
2.6 管道的读写行为
- 读操作- 有数据
- 无数据
 
- 写操作- 读端全部关闭
 
 本文由作者按照  CC BY 4.0  进行授权