当使用fork()
时,是否可以确保子进程在父进程之前执行,而不在父进程中使用wait()
?
这与Operating Systems: Three Easy Pieces的Process API chapter中的一个家庭作业问题有关,Operating Systems: Three Easy Pieces是一本免费的在线操作系统书籍。
问题是:
1.使用fork()
编写另一个程序。子进程应该打印“hello”;父进程应该打印“再见”。2你应该确保子进程总是先打印;可以 * 不 * 调用父对象中的wait()
来执行此操作吗?
下面是我使用wait()
的解决方案:
#include <stdio.h>
#include <stdlib.h> // exit
#include <sys/wait.h> // wait
#include <unistd.h> // fork
int main(void) {
int f = fork();
if (f < 0) { // fork failed
fprintf(stderr, "fork failed\n");
exit(1);
} else if (f == 0) { // child
printf("hello\n");
} else { // parent
wait(NULL);
printf("goodbye\n");
}
}
经过思考,我决定最后一个问题的答案是“不,你不能”,但后来的一个问题似乎暗示你可以:
1.现在编写一个程序,使用wait()
在父进程中等待子进程完成。wait()
返回什么?如果在子进程中使用wait()
会发生什么?
我是否理解错了第二个问题?如果没有,如何执行第一个问题?如何使子进程先打印而不在父进程中使用wait()
?
4条答案
按热度按时间deyfvvtc1#
在父级中创建一个管道,在
fork
之后,关闭父级中的write half和子级中的read half。然后,
poll
用于可读性,因为子进程从不向它写入数据,所以它会等到子进程(以及所有的孙进程,除非你特别小心)不再存在,这时poll
会给予一个“read with hangup”响应(或者,你可以通过管道进行通信)。您应该阅读关于
O_CLOEXEC
的文章。作为一般规则,除非有充分的理由清除该标志,否则应始终设置该标志。fgw7neuy2#
我不明白为什么第二个问题会暗示第一个问题的答案是"是"。
是的,有很多解决方案可以得到所问的问题,但当然,我怀疑所有的解决方案都不符合问题的"精神",因为问题的重点是
fork/wait
原语。关键是要记住,你不能假设任何关于进程相对于彼此运行的方式的分叉之后的事情。为了确保子进程先打印,你需要在两个进程之间进行某种同步,并且有很多系统原语在进程之间具有"通信"的语义(例如锁、信号量、信号等),我怀疑其中有一个是否适合在这里使用,因为它们通常在本课程稍后介绍。
任何其他尝试只会依赖于时间假设(比如使用
sleep
或循环来"减慢"父进程,等等)会导致失败,意味着你将无法证明它总是会成功。即使测试可能会告诉你它看起来是正确的,你所尝试的大多数运行都不会有导致失败的坏特性。2记住,除了实时操作系统,调度几乎是公平并发的近似。注:
正如Jonathan Leffler所评论的,我还假设使用其他类似
wait
的原语是被禁止的(又名wait4
、waitpid
等)--"精神"参数。pwuypxnk3#
我不确定这是否违背了问题的精神,但我认为在父进程分支中调用
pause
系统调用将导致调度程序立即运行子进程(如果它还没有运行)。ygya80vv4#
我希望这个答复不会太迟。
几分钟前,我给雷米兹(本书作者)发了一封电子邮件,得到了这样一个回放(摘录一些片段):
不调用wait()是很困难的,也不是真正的要点。你所做的--自己学习信号--是一个好兆头,表明你将寻求更深层次的知识。对你来说很好!
稍后,您将能够使用共享内存段以及条件变量或信号量来解决这个问题。