好的,所以这是我们今天的操作系统考试的一个例外
在C
中给出了这个程序#include <unistd.h>
#include <stdlib.h>
int main(){
int i;
for(i=2;i>=1&&!fork();i--)
printf("%d\n",i);
exit(EXIT_SUCCESS);
}
执行它会给出这个输出:
2
1
我发现模糊不清的是程序如何管理索引“i” 什么是流程执行的正确顺序 (如果有订单或者是调度程序建立的随机订单?)
为什么只有2和1印刷 - 我的假设是:
(father executes the "for" only for i=2, prints 2 then exits ?)
(the first child starts from i=1 forks a child prints 1 exits ?)
此时我的问题是:
是否有第二个孩子分叉但没有进入for? 由父亲打印,第一个孩子打印1个?
最后一件事:
如何重写这个fork-conditioned-for以使其更具可读性(例如if语句)
答案 0 :(得分:2)
for()
循环在循环的每次迭代之前检查条件,包括第一个循环。这意味着原始父进程从i = 2
开始并评估i >= 1 && !fork()
。 fork()
向父项返回非零PID,向子项返回零,因此父项中的!fork()
为false,并且不执行循环:父项退出。
在第一个孩子中,!fork()
为真,因此循环执行。它打印2
,然后递减i
。它现在执行i >= 1 && !fork()
- 再次,!fork()
在第一个子节点中为false,因此它退出for循环和程序。
在第二个孩子(第一个孩子的孩子)中,!fork()
返回true,因此循环执行。它打印1
,然后递减i
。它现在评估i >= 1 && !fork()
。由于i >= 1
评估为false,因此永远不会调用fork()
;它退出循环和程序。此时所有流程都已退出。
您可以将for()
循环重写为while()
循环,并对&&
进行明确的短路评估:
int main()
{
int i;
i = 2;
while (i >= 1) {
if (fork() != 0)
break;
printf("%d\n", i);
i--;
}
exit(EXIT_SUCCESS);
}
答案 1 :(得分:2)
当你fork
时,就像所有程序都被复制粘贴一样,两个相同的过程从那一点开始(尽管父亲得到了孩子的PId作为fork
的返回值和孩子得到零)
那么i
会发生什么,它会在子节点中具有与fork中父节点相同的值。
所以,当i
为2时:
for parent: i>=1 && !fork() <-- fails
for child1: i>=1 && !fork() <-- succeeds
所以,2由原始程序的孩子打印。
现在父级已退出且child1正在运行。它执行i--
,现在i
为1:
for child1: i>=1 && !fork() <-- fails
for child1.1: i>=1 && !fork() <-- succeeds
再次,child1退出,其子,child1.1进入for并打印1.然后执行i--
,i
变为0,i>=1
失败,因为{ {3}},fork
未执行。这个孩子1.1也退出了。
要回答您的上一个问题,通常会写fork
的方式:
pid_t pid = fork();
if (pid)
{
// in parent
}
else
{
// in child
}
现在您只需要一个for循环:
#include <unistd.h>
#include <stdlib.h>
int main(){
int i;
for(i=2;i>=1;i--)
if (fork())
break; /* parent wants to break */
else
printf("%d\n",i); /* child prints something */
exit(EXIT_SUCCESS);
}