有人可以解释一下这是如何工作的吗?fork(),sleep()
Can someone please explain how this works?fork(),sleep()
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include<stdlib.h>
int main(void)
{
pid_t pids[10];
int i;
for (i = 9; i >= 0; --i) {
pids[i] = fork();
if (pids[i] == 0) {
printf("Child%d\n",i);
sleep(i+1);
_exit(0);
}
}
for (i = 9; i >= 0; --i){
printf("parent%d\n",i);
waitpid(pids[i], NULL, 0);
}
return 0;
}
这里发生了什么? sleep()
如何在 for
循环中执行?什么时候被调用?这是输出:
parent9
Child3
Child4
Child2
Child5
Child1
Child6
Child0
Child7
Child8
Child9 //there is a pause here
parent8
parent7
parent6
parent5
parent4
parent3
parent2
parent1
parent0
请解释这个输出。我无法理解它是如何工作的。
一步步分析就好了。
在第一个循环中,原始 (parent) 进程派生了 10 个自身副本。每个 child 进程(通过 fork()
返回零这一事实检测到)打印一条消息,休眠,然后退出。所有 children 基本上是同时创建的(因为 parent 在循环中做的很少),所以当它们中的每一个被第一次安排时它有点随机 - 因此他们消息的乱序。
在循环期间,构建了一个 child 进程 ID 数组。在所有 11 个进程中都有 pids[]
数组的副本,但只有在 parent 中它是完整的 - 每个 child 中的副本将缺少 lower-numbered child PID,并且其自身的 PID 为零。 (这并不重要,因为只有 parent 进程实际使用这个数组。)
第二个循环只在parent进程中执行(因为在该点之前所有child人都已经退出),等待每个child退出。它等待先睡了 10 秒的 child;所有其他人早已退出,因此所有消息(除了第一条)都快速连续出现。这里不可能随机排序,因为它是由单个进程中的循环驱动的。请注意,第一条 parent 消息实际上出现在任何 children 消息之前 - parent 能够在任何 child 进程能够之前继续进入第二个循环开始。这又只是进程调度程序的随机行为 - "parent9" 消息可能出现在 "parent8".
之前的序列中的任何位置
我看到你用 "zombie-processes" 标记了这个问题。 Child0 到 Child8 在这种状态下花费一秒或更多秒,在他们退出的时间和 parent 对他们执行 waitpid()
的时间之间。 parent 在退出之前已经在等待 Child9,因此一个进程基本上没有时间成为僵尸。
如果每个循环中有两条消息 - 一条在 sleep
/waitpid
之前,一条在之后,则此示例代码可能会更有启发性。颠倒第二个循环的顺序(或等效地,将第一个循环更改为 sleep(10-i)
)也是有益的。
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include<stdlib.h>
int main(void)
{
pid_t pids[10];
int i;
for (i = 9; i >= 0; --i) {
pids[i] = fork();
if (pids[i] == 0) {
printf("Child%d\n",i);
sleep(i+1);
_exit(0);
}
}
for (i = 9; i >= 0; --i){
printf("parent%d\n",i);
waitpid(pids[i], NULL, 0);
}
return 0;
}
这里发生了什么? sleep()
如何在 for
循环中执行?什么时候被调用?这是输出:
parent9
Child3
Child4
Child2
Child5
Child1
Child6
Child0
Child7
Child8
Child9 //there is a pause here
parent8
parent7
parent6
parent5
parent4
parent3
parent2
parent1
parent0
请解释这个输出。我无法理解它是如何工作的。 一步步分析就好了。
在第一个循环中,原始 (parent) 进程派生了 10 个自身副本。每个 child 进程(通过 fork()
返回零这一事实检测到)打印一条消息,休眠,然后退出。所有 children 基本上是同时创建的(因为 parent 在循环中做的很少),所以当它们中的每一个被第一次安排时它有点随机 - 因此他们消息的乱序。
在循环期间,构建了一个 child 进程 ID 数组。在所有 11 个进程中都有 pids[]
数组的副本,但只有在 parent 中它是完整的 - 每个 child 中的副本将缺少 lower-numbered child PID,并且其自身的 PID 为零。 (这并不重要,因为只有 parent 进程实际使用这个数组。)
第二个循环只在parent进程中执行(因为在该点之前所有child人都已经退出),等待每个child退出。它等待先睡了 10 秒的 child;所有其他人早已退出,因此所有消息(除了第一条)都快速连续出现。这里不可能随机排序,因为它是由单个进程中的循环驱动的。请注意,第一条 parent 消息实际上出现在任何 children 消息之前 - parent 能够在任何 child 进程能够之前继续进入第二个循环开始。这又只是进程调度程序的随机行为 - "parent9" 消息可能出现在 "parent8".
之前的序列中的任何位置我看到你用 "zombie-processes" 标记了这个问题。 Child0 到 Child8 在这种状态下花费一秒或更多秒,在他们退出的时间和 parent 对他们执行 waitpid()
的时间之间。 parent 在退出之前已经在等待 Child9,因此一个进程基本上没有时间成为僵尸。
如果每个循环中有两条消息 - 一条在 sleep
/waitpid
之前,一条在之后,则此示例代码可能会更有启发性。颠倒第二个循环的顺序(或等效地,将第一个循环更改为 sleep(10-i)
)也是有益的。