在Linux下使用pipe()实现父子进程之间相互通信时遇到的问题及解决

发布时间 2023-03-22 21:13:34作者: kingdom365

今天在做MIT6.S081操作系统课程的lab1时,有这样一个题目:

实现父子进程之间通信,达到'ping-pong'指令的效果。

其实是个很简单的实验,对吧?

准备两个管道,父进程写---子进程读---子进程写---父进程读。

 

但是今天我遇到了这样一个问题:

起初,是一个bug,我发现子进程可以read到父-子管道中父进程写的数据,但是子进程没法通过子-父管道写了;很是让我恼火。

最后,我发现我创建子进程的时机有问题:我把创建子进程放在申请管道之前了

将fork放在申请pipe之后就正常了。

 

 

但是之前出现的错误,让我疑惑:如果说子进程在申请两个管道之前就创建了,那按照一般的(注意这里我并不了解linux的一些机制)想法,子进程中应该不会拿到这两个管道,因为子进程复制父进程内存空间时,父进程内存空间中并不存在这两个管道。

 

(如图,必须将fork放在pipe之后)

之后,我通过阅读linux-unix编程手册和查阅博客,我才明白,这和我之前粗略了解的一个技术有关——LInux的写时复制技术;

也就是说,在子进程被创建的时候,OS中只会多一个指向父进程的指针,这个时候OS已经认为子进程完成创建了,但是很显然,实际上并没有复制;

那么什么时候真正地复制呢?

在Linux中,父进程内存空间中的内容发生改变时,才会真正地将内存空间复制给子进程;也就是说,当第一个管道被申请完毕之后,子进程才会真正地进行拷贝。

这就是出现之前”诡异“现象的原因,子进程只复制了一个父-子管道,没有复制子-父管道;这就造成了子进程能够接收父进程的消息,但是没法向父进程发送消息。

当然,正在写这篇博客的我还是个linux小小白,对于更复杂的机制还不了解,所以如果路过的你发现这篇博客内容是错误的,请及时指出,避免让我在错误的道路上越走越远^_^