C 进程中的fork()、wait()和exit()功能
我有一个C源代码,如下所示C 进程中的fork()、wait()和exit()功能,c,unix,operating-system,fork,wait,C,Unix,Operating System,Fork,Wait,我有一个C源代码,如下所示 #include<stdio.h> #include<stdlib.h> #include<sys/wait.h> #include<unistd.h> #include<sys/types.h> int main(void) { pid_t process_id; int status; if (fork() == 0) { if (fork() == 0)
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
#include<sys/types.h>
int main(void) {
pid_t process_id;
int status;
if (fork() == 0)
{
if (fork() == 0)
{
printf("A");
} else {
process_id = wait(&status);
printf("B");
}
} else {
if (fork() == 0)
{
printf("C");
exit(0);
}
printf("D");
}
printf("0");
return 0;
}
#包括
#包括
#包括
#包括
#包括
内部主(空){
进程id;
智力状态;
如果(fork()==0)
{
如果(fork()==0)
{
printf(“A”);
}否则{
进程id=等待(&状态);
printf(“B”);
}
}否则{
如果(fork()==0)
{
printf(“C”);
出口(0);
}
printf(“D”);
}
printf(“0”);
返回0;
}
当我在终端执行它时,我得到了一些输出,显示在这张图中:
实际上,我对这些输出是如何生成的感到困惑。例如,D0A0~$B0C是如何生成的
有谁能解释一下这些输出是如何生成的,以及
是否在此代码中退出(0)?如果您有这样的代码,一般情况下
if (fork() == 0) {
printf("I'm a child\n");
} else {
printf("I'm a parent\n");
}
printf("This part is common\n");
然后,fork()结果为零的if分支将在子进程中执行,非零分支将在父进程中执行。在这之后,执行将在两个进程中继续(仍然是异步的),因此子进程和父进程都将在if之后执行代码。我们可以用下图来表示它,显示将在每个分支中执行的代码:
fork()
/ \
------- parent ---------- ---------- child -----------
| |
| |
printf("I'm a parent\n"); printf("I'm a child\n");
printf("This part is common\n"); printf("This part is common\n");
现在,让我们为您的代码制作相同的图表。在第一个fork之后,如果出现以下情况,则根据最顶层分割执行:
fork()
/ \
--------- parent --------- ---------- child -------------
| |
| |
if (fork() == 0) if (fork() == 0)
{ {
printf("C"); printf("A");
exit(0); } else {
} process_id = wait(&status);
printf("D"); printf("B");
}
// Common code // Common code
printf("0"); printf("0");
return 0; return 0;
在父级和子级中执行下一个fork之后,我们将得到以下树结构:
fork()
/ \
---- parent ------ ------ child ------
| |
fork() fork()
/ \ / \
--- parent --- --- child --- --- parent --- --- child ----
| | | |
| | | |
printf("D"); printf("C"); process_id = wait(&status); printf("A");
exit(0); printf("B");
printf("D");
printf("0"); printf("0"); printf("0"); printf("0");
return 0; return 0; return 0; return 0;
注意printf(“D”);出现在父-父分支和父-子分支中,因为它实际上是这两个分支中位于if(fork()==0){}
之后的公共代码
此时,所有4个进程都在异步执行
- 父进程打印“D”,然后打印“0”,然后退出
- 父子进程打印“C”,然后退出
- 子-父进程等待其子进程的完成,然后打印“B”,然后打印“0”并退出
- 子进程打印“A”,然后打印“0”,然后退出
- 父控件获取控件。它打印“D0”并退出,控件返回shell
- 子-父进程获取控件。它开始在子进程上等待(正在阻塞)
- 子进程获取控件。它打印“A0”并退出
- 同时,shell进程获取控件并打印命令提示符“~$”
- 子-父进程获取控件。由于子进程已完成,它将被取消阻止,打印“B0”并退出
- 父子进程获取控件,打印“C”并退出
组合输出为“D0A0~$B0C”。它解释了示例中的最后一行。这里涉及四个过程,我们称它们为
a
,b
,c
,和d
(d
是b
和c
,而b
是a
的父级):
是执行第一个d
调用(创建进程fork(2)
)的父进程。由于它是父级,它将转到第一个b
的if
语句,并将else
(创建进程再次fork(2)
),然后在末尾打印字符串c
(两个字符总是在一个D0
调用中一起写入,如write(2)
缓冲数据,请参见下面的原因)printf(3)
的第一个fork生成进程d
,在执行第二个b
(获取进程fork(2)
)后,等待它完成,然后打印a
B0
的第二个b
(好吧,fork()
是在列表的第一个fork之后创建的,并且只执行一个fork,但它是列表中的第二个fork),生成进程b
,打印a
,然后退出,使进程A0
能够在b
调用并打印等待(2)之后继续
,这将强制顺序始终为B0
在A0
之前B0
- 第三个
生成进程fork()
,其任务是打印c
和c
。(这样就不会输出退出(3)
,而只输出C0
)C
- 由于
不等待它的两个子项中的任何一个,一旦打印了d
,它D0
s,使shell输出提示退出(3)
,并等待新命令。这将强制在shell提示之前执行命令~$
D0
是您按下的控件-C,认为程序仍在运行,它使shell在新行中发出第二个提示^C
D0
之后打印提示)和进程b
等待进程a
(强制总是在B0
之前打印A0
)允许任何其他顺序,取决于系统如何安排进程。这包括提示。认为消息总是在所有任务执行结束时打印
shell
`-d
+-b
| `-a
`-c
printf("D");
...
printf("0");