Linux下PIPE和FORK使用需要注意的一个问题

一、前提情况描述

1. linux系统,有父子进程,本案例中,一个父进程,三个子进程。

2.子进程都要使用管道与父进程通信,父进程收到的终端数据,分别通过管道(pipe)发送给3个子进程,子进程(3个)收到数据后,通过(另一个)管道(pipe)将数据(原封)发送给父进程,父进程读出管道的数据,打印到终端。

3.正常情况下,管道应该是6个,父进程与3个子进程之间分别有两个管道。

二、故障现象描述

1. 父进程收到终端的数据,将数据发送到子进程,子进程返回数据给父进程,父进程能正常打印出子进程的数据,该功能(3个子进程都)正常。

2. 有一个子进程收到父进程的数据,除了发送给父进程外,还需要写到指定的文件中。但是这个文件(文件是存在的)没有任何数据,文件字节大小为0.

3. 父进程收到终端的EOF,进程结束,父进程正常退出了。

4. 删除2步骤中指定的文件,再次运行程序时,会产生一个0字节的文件;或者在文件中写入内容,再次运行程序时,文件大小被改为0.

三、问题的解决

1. 前期一直不知道是什么原因,程序运行正常,但是对应的文件内容为0,就感觉很奇怪。

2. 用stat命令查看文件的时间,发现创建时间,修改时间,访问时间均相同,那就是只创建了,没有写入数据。用一个可行的程序发现,创建时间与修改时间差了4秒。看来文件被创建,但是没有被写入。

3.考虑到文件写入的内容不足100个字节(文件缓存一般是4k左右),还不足以自动刷新缓存。但是子进程不是我自己写的,无法加入刷新缓存操作。

4.考虑进程异常结束(缓存没有被刷新)?或者进程没有结束?(缓存不会被刷新)。使用ps命令一看,果然有很多子进程还在跑着。

5.问题定位到,父进程终止,而子进程没有终止(不是说父进程终止,子进程就必须要终止,这里是有条件的。)。什么原因呢?。

6.我猜是pipe的端口没有正常关闭。仔细(反复看了不少于10遍)看了源码,看到父进程和子进程在进入的时候,都关闭掉了自己不用的pipe端口了呀。

7.父进程终止的时候,与子进程的pipe的写段和读端都关闭了,这时候子进程再读的话应该会读到EOF,或者写pipe的时候,应该也是出错,这时,子进程应该就结束了呀。(理论应该是这样)

8.找不到破绽,因为是普通用户,无法查看/proc/pid/fd目录的情况(提示没有权限)。

9.硬着头皮返回代码,发现,在创建子进程(fork)之前,父进程(一次性)已经申请了6个管道。fork之后每个子进程都持有子进程之间的管道读写端。

 

10.找到父进程终止(再次读管道会读到EOF,写管道会报错)的原因。是因为即使父进程关闭了管道的读写端,但是仍然有(其他)子进程持有读写端,所以读写该管道的子进程不会读到EOF,写管道也不会出错,造成子进程仍然等待。

11.解决:需要在每一次fork之前创建每个子进程需要使用的两个管道。(而不是一次性把管道全部创建后,再去三次fork)。父进程需要关闭不需要的端口,然后再下一次创建两个管道给下一个子进程,然后再fork,依次类推。

12.修改了创建管道的时机后,问题得到解决。(父进程退出后,子进程也跟着结束了)。

13.本案例中如果只有一个子进程,不会出现上述问题。

14.fork使用确实很简单(逻辑功能可能会变得比较复杂),配合着其他功能,可能就会出现莫名的问题。(有需要的同学借鉴一下)

15.本案例中,管道还是6个,但是每个管道就分别被4个进程持有相关的读端和写端(尤其是不相干的两个子进程,是持有另一个子进程与父进程管道的读端和写端的,他们没有做任何关闭操作)。正常情况应该是只有父进程持有6个管道的部分读写端,而每个子进程应该只持有一个管道的写端和另一个管道的读端,每个子进程应该拥有不同于另外两个子进程的(两个)管道。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大智兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值