一个程序在循环中调用 fork 并进行 N 次迭代,会创建多少个进程?

问题描述 投票:0回答:8
#include<stdio.h>
#include<unistd.h>

int main()
{
    int i;
    for(i=0;i<4;i++)
        fork();
    return 0;
}

我的问题:包括初始父进程在内,程序创建了多少个进程?

我认为这个答案是1+4=5,1个父进程和4个子进程。我说得对吗?

c operating-system fork
8个回答
13
投票

使用 fork() 四次的答案是:2 * 2 * 2 * 2 - 1 = 16 - 1 = 15 个进程。


9
投票
for(i=0;i<4;i++)
    fork();

这段代码相当于:

fork();
fork();
fork();
fork();

假设该进程从 p0 开始。流程图将如下所示:

Process-creation diagram

上图说明了一切,当第一个 fork() 执行时,它会创建一个新进程,剩下三个 fork() 需要执行。现在,这里存在一个父线程和一个子线程来执行另外三个 fork() 语句。因此,子进程 p1 将创建 p5、p6 和 p7,父进程将创建 p2、p3 和 p4。 创建 p2 后,需要为该子线程 p2 执行两个以上的 fork() ,该子线程 p2 是在执行第二个 fork() 语句后创建的。 这样,这个父子进程就创建好了。


4
投票

尝试在程序末尾添加睡眠语句,如下所示:

#include<stdio.h>
#include<unistd.h>

int main()
{
    int i;
    for(i=0;i<4;i++)
        fork();
    sleep(10000);
    return 0;
}

接下来,编译并运行您的程序。然后运行

pstree
查看进程层次结构是什么样的。


0
投票

很简单,在这个问题中你只是注意到问题说包括初始父进程,所以在这种情况下 2 * 2 * 2 * 2 - 1 是创建的进程数,因为问题说包括初始父进程家长,答案是16。 祝你好运:)


0
投票

enter image description here

这个解决方案的灵感来自操作系统参考书,这意味着每个级别的父进程都会进入下一个分支,并且上一个分支终止,因此我们只计算叶子。


0
投票

根据问题: n = 4 总数可以创建的进程=

2^n
=
2^4
=
16
.


0
投票

最推荐的答案实际上是错误的。 这是因为 fork() 的第一次调用将创建父级的 4 个子级中的第一个子级,并且第一个子级将有 3 个剩余的 fork() 调用,这意味着它将创建 3 个子级,而这 3 个子级中的第一个子级将创建创建 2 等等。最推荐的答案错过的是最左边叶子上的最后一个孩子。

4 fork() calls total creation of processes


0
投票

获取代码

for (int i = 0; i < 4; i++) fork();

您可以展开循环并注释步骤:

fork(); // 1 process will execute this fork, 2 processes exist afterwards
fork(); // 2 processes will execute this fork, 4 processes exist afterwards
fork(); // 4 processes will execute this fork, 8 processes exist afterwards
fork(); // 8 processes will execute this fork, 16 processes exist afterwards

将有 15 个子进程和 1 个父进程,总共 16 个。进程树如下所示:

a─┬─b─┬─f─┬─l───p
  │   │   └─m
  │   ├─g───n
  │   └─h
  ├─c─┬─i───o
  │   └─j
  ├─d───k
  └─e

a
进程会产生 4 个子进程:
b
c
d
e
b
在第一个
fork()
之后开始,并生成 3 个子级:
f
g
h
c
在第二个
fork()
之后开始并生成 2 个子级。等等。这些子级中的每一个在执行中都有
fork()
,因此它们会“递归”生成更多子级。

OP 尝试的问题在于它没有考虑分支——当子进程在执行中遇到

fork()
时,它们会产生更多的子进程。

现有答案提供了不同程度有用的解决方案,但这里有一个在纸上解决此类问题的通用方法(假设家庭作业/考试场景,您无法运行代码),无论代码结构如何(可能存在分支和其他技巧)。

从 1 个进程开始,并从其

main()
开始。在心里通过操作来执行代码操作。当您遇到
fork()
调用时,请在心里复制代码,并在
fork()
返回后,从完全相同的程序点继续在子进程上执行。这很难跟踪,因此您可以如上所述展开循环,然后用执行它的子级数量注释每个分叉,同时考虑分支和控制流。

© www.soinside.com 2019 - 2024. All rights reserved.