为了深入了解匿名管道的特性,我们需要了解管道通信的四种情况
(1) 子进程写入的速度 远大于 父进程读取的速度
(2) 父进程读取的速度 远大于 子进程写入的速度
(3) 子进程正在写入,但是父进程关闭了文件描述符
(4) 子进程写完一批数据以后关闭文件描述符,父进程在读取
目录
2、子进程写入的很快,父进程每次只读取一个(测试父进程取数据时,子进程是否会继续写入)
3、子进程写入的很快,父进程每次至少读取4KB(4096 bytes)
一、子进程写入的很快,父进程读取的很慢甚至不读取
1、子进程写入快,父进程不读取(目的是测试管道大小)
这样的结果可想而知,因为管道是有大小的!!所以管道被填满以后就不会继续往里面写入了,这个时候子进程会等待父进程去取数据
那么管道到底有多大呢?我们下面可以测试一下
我们发现到了写入65536个字符以后,子进程就不再写入了,换算一下,65536正好就是64KB,所以我们知道 Linux系统中管道的大小是64KB
2、子进程写入的很快,父进程每次只读取一个(测试父进程取数据时,子进程是否会继续写入)
管道被写满的时候,就说明子进程要等待父进程取数据了,那么是不是说,父进程取数据了,子进程就会继续写入了??
根据结果我们发现,父进程读取了好几次,但是子进程的count依然没有什么变化,那父进程要读取多少才能写入呢?答案是 4KB
我们可以在pipe函数的定义中找到答案
3、子进程写入的很快,父进程每次至少读取4KB(4096 bytes)
现在设置父进程每次读取的字符数为 4096,我们来继续测试
我们发现子进程在父进程取出数据以后,又开始写入了!所以这就验证了,管道写满以后,父进程每次至少要读取4KB,即4096个字符,子进程才会继续写入
二、父进程读取的速度大于子进程写入的速度
现在我们设置成子进程每隔10s向管道里写入数据,然后父进程通过while循环不断读取,而且打印读取的字符数
我们可以看到,字符数没有一直打印,而是等父进程读取到数据以后再打印,这也就说明当管道里没有数据可读的时候,父进程会等待子进程写入数据
三、子进程正在写入,但是父进程关闭了文件描述符
子进程每隔1s写入一次数据,父进程休眠3s以后就关闭读取的文件描述符pipefd[0],然后退出进程,这个时候我们顺带通过子进程的退出码和退出信号来检测一下子进程是否会正常突出
这个时候子进程会继续一直写入吗??
我们根据测试结果发现,一开始两个进程都在运行,但是最后两个进程都退出了,这就说明父进程退出以后,子进程不会继续写入
父进程都退出了,但是子进程还在一直写入,OS认为这是一种十分浪费资源的行为,于是会给子进程发送一个SIGPIPE信号 来杀死子进程
四、父进程在一直读取,但是子进程写入一串字符以后就退出了
子进程写入一串字符以后,退出进程;父进程每隔1s读取一个字符
我们先来看看打印的结果,父进程读取完子进程写入的内容以后,也会自动退出,和上面一样,这也是OS无法容忍的行为,因为无数据可读,还要一直读,就是在浪费资源
下面我们继续看一下进程的运行过程,和上面的结果基本吻合
五、匿名管道的五个特性
(1) 管道是一个只能单向通信的通信信道。
(2) 管道是面向字节流的!无论是从管道读取,还是向管道写入,都是以字节为单位写入的!
(3) 匿名管道仅限于父子通信(有血缘关系的进程之间的通信)
(4) 管道自带同步机制,当父进程读取了足够的数据以后,子进程会自动继续写入
(5) 管道是文件!!如果一个文件在当前进程被打开,相关进程退出了(会自动递减struct file的引用计数),打开的文件会自动被OS关闭!
—》管道的生命周期是随进程的(相关进程退出以后,管道也会被关闭)