fork()系统调用(C程序)的工作

时间:2016-02-18 07:12:08

标签: c fork

当我运行此代码时,它会打印“hello world”20次。根据我的理解,它应该打印32次。此外,每次运行时换行符的打印方式也不同。我不明白这一点。请帮忙。

int
main(int argc, char** argv){
    if(fork() || fork())
        fork();
    if(fork() && fork())
        fork();
    printf("\nhello world");
    return 0;
}

3 个答案:

答案 0 :(得分:4)

要理解你必须同意这两种结构。首先是构造

if( fork() || fork() )
    fork();

或通过展开短路或其他方式书写:

if( !fork() )
    if( !fork() )
        goto not_taken;
fork();
not_taken:

或没有goto

if( !fork() ) {
    if( fork() )
        fork();
}
else
    fork();

将是进程数量的五倍。这是因为首先原始进程分叉,然后作为fork的子进程将返回零,它将再次fork(短路或)。然后,如果其中任何一个返回非零(即fork的父级),它将再次fork - 这恰好在父进程中完成,并且它是子进程。也就是说,条件中的fork将被调用一次,最后fork将被调用一次。

现在是第二个结构:

if( fork() && fork() )
    fork();

或展开短路并且:

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

过程计数将是四倍。原因是第一个fork将在父进程中运行,如果返回非零(即父进程),则将调用第二个fork,如果返回非零,则返回非零将。所以这里所有三个fork都在原始进程中被调用 - 这意味着它被调用了三次。

因此,第一个构造将使它们成为五个进程,第二个构建将为每个进程创建三个进程。这意味着我们将拥有5*4个进程。

您没有获得一致换行符的原因可能主要是printf缓冲。 printf只会立即打印出换行符,然后在终止时写入剩余的数据,这意味着它们分两步打印字符串。我们有20个进程首先打印换行符然后同时打印“hello world” - 不能保证不同进程打印的顺序。

一个小的可能性是实际的打印输出不需要是原子的。这是一个过程可能会写“地狱”,然后第二个已经写成“你好”的东西可以写成“世界” - 这将导致“地狱世界”。

答案 1 :(得分:0)

让我们计算每个fork调用的次数。在这个区块中有3个叉子:

if(fork() || fork())
    fork();

第一个分支在第一个过程中被称为1时间。

第二个进程只调用第二个分叉1次。 (第一个过程没有达到它)

第3个分支在第一个和第二个过程中被称为2次。

所以,此时你已经有 5 个过程。

对于这个区块,还有另外3个分叉:

if(fork() && fork())
    fork();

第一个叉子称为1 x 5 次。在这里,分叉的子进程直接转到printf

第二叉称为1 x 5 次。仍然,分叉子进程转到printf

第3个分支称为1 x 5 次。

所以你总共20

答案 2 :(得分:0)

如果分别评估两个if结构,这会容易得多。计算在第一个中创建的进程数,并将其乘以在第二个中创建的数。结果是进程总数和调用printf调用的次数。

(我们假设fork调用不会失败。)

第一个if语句由这个方便的图表显示,其中列是分叉,行是进程。 叉子 - f1,f2,f3
进程 - c0,c1,...,c4
xN - 标记过程的创建,其中N是创建的过程的索引
。 - 标记流程创建
_ - 过程存在且不执行任何操作 (没有字符表示此时不存在该过程)

        f1  f2  f3
c0  _   x1  _   x2  _
c1      .   x3  x4  _
c2              .   _
c3          .   _   _
c4              .   _

此时存在5个进程,另外创建了4个进程。下一个图表显示了第二个if语句,但仅适用于一个进程:

        f1  f2  f3  
c0  _   x1  x2  x3  _   
c1      .   _   _   _
c2          .   _   _
c3              .   _

这个if语句创建了3个额外的进程,因此存在4个进程。但请记住,我们之前有5个流程,而不仅仅是一个。因此,两个if语句一起创建5 x 4个进程,总共20个。