我最近遇到了这段代码,但并不完全理解。
基本上,我不完全理解下面的输出。任何帮助,将不胜感激。谢谢。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // standard POSIX header file
#include <sys/wait.h> // POSIX header file for 'wait' function
int main(void)
{
int i = -1;
int pid;
pid = getpid();
fprintf(stdout, "parent pid = %d\n", pid);
pid = fork();
if (pid == 0)
{
for (i = 0; i < 10; ++i)
{
fprintf(stdout, "child process: %d\n", i);
sleep(1);
}
exit(0);
}
else
{
fprintf(stdout, "child pid = %d\n", pid);
fprintf(stdout, "waiting for child\n");
wait(NULL);
fprintf(stdout, "child terminated\n");
}
fprintf(stdout, "parent terminating\n");
return 0;
}
输出:
parent pid = 2896
child pid = 5840
waiting for child
child process: 0
child process: 1
child process: 2
child process: 3
child process: 4
child process: 5
child process: 6
child process: 7
child process: 8
child process: 9
child terminated
parent terminating
答案 0 :(得分:3)
如Susmit Agrawal和Jonathan Leffler的评论中所述,简要回答您的第一个问题:
0
是在成功返回fork()
调用之后,在子进程中的返回值。子进程的执行从if (pid == 0)
块开始。每次迭代都在for
循环,prints
和sleeps
上进行迭代,然后最后调用exit(0)
,子进程终止。
fork()
调用之后,父进程的执行在else
块中继续。在父进程中返回的 PID 是孩子的 PID 。
要简短回答第二个问题:
wait(NULL
)用于等待子进程状态的改变。在这种特定情况下,状态更改是子项的终止。参数NULL
仅表示不会存储任何状态信息。
有关更多详细信息,请阅读链接的手册页。
答案 1 :(得分:1)
fork(2)
系统调用将创建第二个子进程,因此,该调用在父级中被调用一次,但在父级和子级中均返回。
由于这个原因,调用后的代码需要一些指示来知道我们是在父级还是子级中执行代码,因为这允许父级和子级从此刻开始从公共代码转移。
fork(2)
的定义及其在手册页中的说明是:
-1
并将errno
设置为一个指示fork(2)
调用失败的值。0
。pid_t
子进程ID返回给父进程(一个正数),以便它可以知道刚刚启动的新子进程的pid。 wait(NULL);
不在if (pid == 0)
中,而是在else
部分中,因此它确实在if (pid != 0)
或父进程中。出于以下几个原因,父进程必须知道子进程是否已完成以及如何完成同步,并且必须与之同步:
孩子可以exit(2)
在父母之前,但是根据孩子的工作量,孩子可以在父母完成之后做。如果父母在孩子之前结束,您将再次得到shell提示,并且在发出提示后,屏幕上的孩子的输出将变得模糊。这不是您通常想要的,因此在父级中进行wait(2)
调用只是礼貌,因此shell仅在一切完成后提示您。
一个好的测试是在您的示例中评论wait(2)
调用,看看会发生什么。
wait(2)
系统调用是一种了解孩子如何结束运行的方式(主要是如果您在孩子的过程中exec(2)
还有其他程序),您可以了解孩子是否死于exit(2)
被打开(并接收其退出代码),因为它被打断(以及接收到的信号是什么),或者由于某种原因已被用户/系统停止。
阅读fork(2)
,exec(2)
,exit(2)
和wait(2)
系统调用(全部作为一组相关调用)将启发所有过程关系以及所有这些关系系统调用协作来管理unix流程系统。