使用fork()
时,是否可以确保子进程在父进程之前执行而不在父进程中使用wait()
?
这与免费在线操作系统手册Process API chapter Operating Systems: Three Easy Pieces中的作业问题有关。
问题是:
- 使用
醇>fork()
编写另一个程序。子进程应该 打印“你好”;父进程应打印“再见”。你应该 尽量确保子进程始终先打印;你可以做 这个没有在父母中调用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");
}
}
在考虑之后,我决定最后一个问题的答案是“不,你不能”,但后来的问题似乎暗示你可以:
- 现在编写一个使用
醇>wait()
等待子进程的程序 完成父母。wait()
返回什么?如果发生什么 你在孩子身上使用wait()
吗?
我是否错误地解释了第二个问题?如果没有,你怎么做第一个问题要求?如何在父母不使用wait()
的情况下首先打印孩子?
答案 0 :(得分:1)
我无法理解为什么第二个问题会暗示答案是&#34;是&#34;到第一个。
是的,有很多解决方案可以获得所要求的内容,但当然我怀疑所有这些都不属于&#34;精神&#34;关注fork/wait
原语的问题/问题。重点是要记住,在关于流程相对于彼此运行的方式之后,你不能假设任何事情。
为了确保子进程首先打印,您需要在两个进程之间进行一种同步,并且有许多系统原语具有&#34;通信&#34;进程之间(例如锁,信号量,信号等)。我怀疑其中一个是用她的,因为它们通常会在稍后的课程中稍后介绍。
任何其他仅依赖于时间假设的尝试(例如使用sleep
或循环来减少&#34;向下父母等)会导致失败,意味着你不会能够证明它将永远成功。即使测试可能会向您显示它似乎是正确的,但您尝试的大多数运行都不会具有导致失败的不良特性。请记住,除了在实时操作系统中,调度几乎是公平并发的近似值。
注:
正如Jonathan Leffler评论的那样,我还假设禁止使用其他wait
- 类原语(aka wait4
,waitpid
等) - &#34; spirit&#34;参数。
答案 1 :(得分:1)
我希望这个答案对某些人来说并不晚。
几分钟前,我已经通过电子邮件发送给了Remiz(这本书的作者),并获得了这样的重播(摘录了一段):
没有调用wait()很难,而不是真正的主要观点。 你做了什么 - 自己学习信号 - 是一个好兆头, 显示你将寻求更深层次的知识。对你有好处!
稍后,您将能够使用共享内存段,并且 无论是条件变量还是信号量,都可以解决这个问题。
他是一位非常负责任的教育家,作家和教授:P
答案 2 :(得分:0)
在父级中创建管道。在fork
之后,关闭父级中的写半部分和子级中的读半部分。
然后,poll
以提高可读性。由于孩子从不写信,它会等到孩子(以及所有孙子,除非你特别小心)不再存在,此时poll
会给出一个&#34;读取与挂断&#34;响应。 (或者,您实际上可以通过管道进行通信)。
您应该阅读O_CLOEXEC
。作为一般规则,除非您有充分的理由清除该标志,否则应始终设置该标志。
答案 3 :(得分:0)
我所做的只是在else条件中放置了一个for循环,以便父进程不会立即完成,而子进程将首先打印。但是我想这在技术上并不是在等待子进程,也没有一个糟糕的解决方案来完成任务。 for(i = 1000; i> 0; i ++); 而且,我也不确定使用这种(非道德的)方法,孩子会总是先打印。