我搜索并搜索无济于事,所以我终于来寻求帮助了。 我的任务涉及(在RedHat Linux上运行的C)创建两个子进程,每个子进程将任意数量的迭代的字符写入管道。此管道与创建它们的父进程共享。父项从管道中读取,而子项仍有要写入的字符。一旦孩子退出并且管道为空,则父(主)可以终止。
这是一个快速的&我编写的代码逻辑的脏例子。
main()
{
//create pipe
fork(); //childA
//writes to pipe
fork(); //childB
//writes to pipe
//parent reading
while(condition) {
//read from pipe + print chars to terminal
}
}
现在,我的问题是关于while循环的条件。 我需要阅读当孩子由于满管而被阻止写字时,但我无法弄清楚允许我这样做的条件是什么类型。任何帮助都绝对令人惊叹。
答案 0 :(得分:0)
当您阅读时,管道是否需要满员?或者只是要求你继续阅读这两个孩子,即使其中一个管道已满,所以孩子在写作时会被阻止?
如果管道已满,我不知道任何标准方法。您可以尝试使用FIONREAD
ioctl来确定要在管道上读取的数据量,并将其与PIPE_BUF
进行比较,但如果小于PIPE_BUF
,则可能无法正常工作管道中的数据,但是孩子正在进行写入,将其置于PIPE_BUF
之上;该调用可能会阻塞而不会填满管道。我不会依赖这种技术。
从两个文件描述符中读取的常用方法是使用select
系统调用,而不管哪一个已准备好。这允许您等到一个或另一个文件描述符具有可用数据。这意味着父进程不会阻止尝试从一个没有任何可用数据的子进行读取,而另一个进程因为缓冲区已满而阻塞。
编辑:重新阅读您的问题后,听起来实际上只有一个管道,两个孩子都在写信。那是对的吗?同样,问题出现在是否需要等到孩子们阻止。如果父母只是从管道读取,它将阻塞,直到其中一个孩子写入管道;你不需要做任何特别的事。
如果您的作业要求您等到管道实际已满,我会有兴趣看到确切的措辞,因为我不确定您为什么要这样做。
编辑2 :在评论中回答您的问题:
我父进程的代码是否需要遵循程序中我的两个子进程的代码?
不,不要求父进程或子进程的代码顺序。为了区分父代运行的代码和子代码运行的代码,检查fork()
的返回值。如果返回值为0,则表示您处于子进程中。如果不是,那么你就是父母;如果返回值为-1,则出现错误,如果为正,则为子进程的PID。
所以,你可以写这样的代码:
int pid = fork();
if (pid) {
// in the parent, check if pid is -1 for errors
} else {
// in the child
}
或者:
int pid = fork();
if (pid == 0) {
// in the child, do whatever you need to do and...
exit(0);
}
// in the parent; since the child calls exit() above, control will never
// reach here in the child. Or you could do an execl() in the child, which
// replaces the current program with another one, so again, control will
// never reach here within the child process.
如果两个孩子终止并且管道是空的,我怎样才能继续读取管道?
只需保持读数直到read
返回0.管道读取端的read
将不会返回0,直到所有进程都关闭了管道的写入端,并且所有数据都已读出管道。如果某些内容仍然打开,但管道中没有数据,read
将阻塞,直到数据写入管道。
一个问题是要记住在尝试read
之前关闭父进程中管道的写端。否则,当父母在孩子完成后尝试做read
时,它会阻止等待它关闭自己的管道。