进程间通信(inter process communite)之管道
1.管道的分类
- 有名管道、没有血缘关系的进程间通讯fifo()
- 无名管道、只能进行父子进程间的通讯pipe()
- 不管是有名管道还是无名管道都是往内核中写数据
2.管道的实现:环形队列
3.管道的大小:4K
4.局限性:数据只能读取一次,不能重复读取,头指针write在前面写,尾指read在后面读,循环读
5.模式:半双工(单项数据流动)
6.创建无名管道
原型:int pipe(int fd[2]);fd是传出参数 fd[0]读端 fd[1]写端
读操作
有数据:read正常读,返回出字节数
无数据
写端全部关闭
1.read接触阻塞,返回0,相当于读文件读到了尾部
2.写端没有全部关闭 read阻塞
写操作
读端全部关闭:管道破裂,进程被终止,内核给当前进程发送SIGPIPE信号
读端没有全部关闭:缓冲区写满了,write阻塞,反之,没有被写满,write继续写
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5
6 int main()
7 {
8 int fd[2];
9 int ret = pipe(fd); //创建一个无名管道
10 if(ret == -1)
11 {
12 perror("pipe failed!");
13 exit(1);
14 }
15
16 pid_t pid = fork();
17 if(pid == -1)
18 {
19 perror("fork error!");
20 exit(1);
21 }
22
23 if(pid > 0) //父进程负责往管道中写入数据
24 {
25 close(fd[0]); //关闭读段
26 dup2(fd[1],1); //用标准输出覆盖管道的写端,把数据写道管道中去
27 execlp("ps","ps","aux",NULL); //这个是父进程执行的命令和参数 ps -aux
28
29 perror("execlp error!");
30 exit(1);
31 }
32 //子进程负责读数据并且打印在终端上
33 if(pid == 0)
34 {
35 close(fd[1]); //关闭写段
36 dup2(fd[0],0); //用标准输入覆盖管道的读端,把数据从管道中读出来
37 execlp("grep","grep","bash",NULL); //执行的命令是 grep | bash
38 perror("grep error!");
39 exit(1);
40 }
41
42
43 close(fd[0]);
44 close(fd[1]);
45 return 0;
46 }
7.有名管道
有名管道原理 :在磁盘上创建一个fifo文件,不管在这个文件内写多少,文件大小都为0,因为在内核中这个fifo文件会有一个对应的缓冲区,写入的数据会导入到这个缓冲区中,所有这个文件大小一直会为0.
两个不相关的进程通信
创建fifo文件命令:mkfifo main
接下来的操作和操作文件,一遍读文件,一遍写文件,这样进程间通信就成功了。