我试图确定以下代码中生成了多少个进程:
#include <stdio.h>
#include <unistd.h>
int main() {
int i = 1;
if (fork()) //parent process will return PID of child.
i++;
else if (fork()) //child process (becomes parent)
i--;
else //grandchild process returns 0
i++;
printf("%d\n", i);
}
通常,进程总数的公式为 2^n,其中 n 是 fork 系统调用的次数。 我很困惑,因为这个示例涉及 if/else 条件语句。
我总共得到 4 个进程。 (来自
if (fork())
语句的 2 个过程和来自 else if (fork())
语句的 2 个过程)。 有人可以确认这是否正确吗?如果没有,您能否指导我正确的方向/解释如何计算进程数。 这是我很难确定的事情。
注意:即使
if ()
没有成功,true
语句也会被评估fork()
,因为在这种情况下它返回一个与0
不同的负数,所以true
。
您有3个进程
第一个
fork()
生成父进程的副本,即子进程。现在你有 2 个进程。 fork() 将子进程 PID 返回给父进程。这使得第一个 if()
条件成为父级的 true
,以及子级的 false
。父级递增变量 i
。
因此,子流程进入第二个 if 语句,该语句在求值之前执行 fork。分叉生成子级的副本(现在成为父级),即孙级。您现在有 3 个进程。
孩子评估
else if
条件 true
并将减少 i
,而孙子评估 false
并将增加 i
。
正如我所说,如果你尝试执行你的程序,你只会得到 3 个输出(3 个
printf()
被执行)。输出的顺序取决于 CPU 调度程序如何调度进程,这是您无法预测的。
代替您的代码,尝试这个:
#include <stdio.h>
#include <unistd.h>
int main()
{
int counter = 0;
if( fork() )
{
// should be the parent
fprintf( stderr, "1. process ID: %d\n", getpid() );
fprintf( stderr, "1. parent process ID: %d\n", getppid() );
++counter;
}
else
if( fork() )
{
fprintf( stderr, "2. process ID: %d\n", getpid() );
fprintf( stderr, "2. parent process ID: %d\n", getppid() );
--counter;
}
else
{
fprintf( stderr, "3. process ID: %d\n", getpid() );
fprintf( stderr, "3. parent process ID: %d\n", getppid() );
++counter;
}
printf( "counter: %d\n", counter );
}
这是运行代码的输出:
ALP ❱ gcc temp.c
ALP ❱ ./a.out
1. process ID: 6672
1. parent process ID: 3037
counter: 1
2. process ID: 6673
2. parent process ID: 6672
counter: -1
3. process ID: 6674
3. parent process ID: 2008
counter: 1
ALP ❱ ps
PID TTY TIME CMD
3037 pts/2 00:00:01 bash
5354 pts/2 00:00:00 redshift
6642 pts/2 00:00:00 ps
ALP ❱ ps -e | grep 2008
2008 ? 00:00:00 upstart
ALP ❱
现在发生的事情是这样的:
3037
是我机器上的 bash 进程 ID
2008
是 upstart
的进程 ID(= 在这里处理僵尸进程)6672
是main
函数6673
是第一个子进程,它的父母是主要的:6672
6674
是第二个孩子进程,2008
(=暴发户)成为它的父母
虽然我不确定,但我猜你在主进程中有 2 个子进程,因此总共有 3 。由于您没有检查
-1
调用fork(2)
的失败,因此在其他运行代码的人身上可能会有所不同。
注意
由于您没有
wait(2)
为您的孩子和主要出口未终止他们,所以 upstart(8)
负责终止他们。
注2
您不应该以这种方式使用
fork(2)
。