繁体   English   中英

当 fork() 处于某个条件时会发生什么?

[英]What happens when fork() in a condition?

谁能给我这个代码的输出(有解释)? 谢谢...

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

int main() 
{ 
    if (fork() && (!fork())) { 
        if (fork() || fork()) {
            fork(); 
        } 
    } 
    printf("Friend\n");
    return 0; 
}

在进入代码之前最好先了解什么是 fork() 系统调用

fork() 系统调用由“父”创建一个新进程,新创建的进程称为“子”进程

当fork成功时,子进程返回0,父进程返回正整数

这就是这里的线索

因此,从该程序计数器开始,所有两个进程都同时工作......

在这里 fork() 处于 if 条件,并且在猜测输出时也有点棘手

  1. 首先 fork() 创建新的 C1 -> 0

  2. 第二个 fork() 创建新的 C2 -> !0 -> 1

所以第一个条件由 C2(其父正整数和 c2 为 0)统计,但未由父或子 C1 统计,因此其他分叉将不起作用

然后 C2 进入另一个 if 条件并制作另外两个叉子

            C2
          /    \
         C2     C3
       /   \   /  \
      C2   c4  c3  c5

然后所有创建的进程(包括父进程)打印“朋友”输出 7 次

快速回答是父母会做某事,而孩子会做其他事情。 但是继续阅读……

好吧,我只是稍微修改了您的代码,您将从程序的输出中获得所有进程层次结构,以及您问题的答案:

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h> 

static pid_t my_fork() /* tracing is your friend! :) */
{
    pid_t chld = fork();
    if (chld > 0) {
        /* only the parent shows this */
        printf("[pid=%d, child=%d] forked!\n",
                getpid(), chld);
    }
    return chld;
}

int main() 
{ 
    /* print our pid, so we know the root of the hierarchy */
    printf("[pid=%d] Hello, world\n", getpid());

    /* do the embarrasing work */
    if (my_fork() && (!my_fork())) { 
        if (my_fork() || my_fork()) {
            my_fork(); 
        } 
    } 

    pid_t pid;
    int status;

    /* We do wait(2)'s while there are children to be waited for. 
     * it's a good thing to wait for children before ending. */
    while((pid = wait(&status)) >= 0) {
        printf("[pid=%d, child=%d]: child ended with status=%d\n",
                getpid(), pid, status);
    }
    
    /* we print the message when no more children are alive */
    printf("[pid=%d]: Hello friend!\n", getpid());

    return 0; 
}

这会产生

$ pru
[pid=72699] Hello, world
[pid=72699, child=72700] forked!
[pid=72699, child=72701] forked!
[pid=72700]: Hello friend!
[pid=72701, child=72702] forked!
[pid=72703]: Hello friend!
[pid=72699, child=72700]: child ended with status=0
[pid=72702, child=72703] forked!
[pid=72702, child=72705] forked!
[pid=72702, child=72703]: child ended with status=0
[pid=72705]: Hello friend!
[pid=72704]: Hello friend!
[pid=72701, child=72704] forked!
[pid=72701, child=72704]: child ended with status=0
[pid=72702, child=72705]: child ended with status=0
[pid=72702]: Hello friend!
[pid=72701, child=72702]: child ended with status=0
[pid=72701]: Hello friend!
[pid=72699, child=72701]: child ended with status=0
[pid=72699]: Hello friend!

这是层次结构:

[pid=72699] (says Hello, world, just starting)
  +-[pid=72700] (created in first fork() call of pid=72699)
  `-[pid=72701] (created in second fork() call of pid=72699)
     +-[pid=72702] (created in third fork() call of pid=72701)
     |  +-[pid=72703] (created in fourth fork() call of pid=72702)
     |  `-[pid=72705] (created in fifth fork() call of pid=72702)
     `-[pid=7204] (created in fourth fork() call of pid=72701)

(当然,如果进程用完了,层次会不一样, fork(2)因为系统资源不足而失败)

最后,您可能会担心为什么消息

[pid=72703]: Hello friend!

出现在消息之前

[pid=72702, child=72703] forked!

但这就是多任务处理的奇妙世界。 fork(2)返回后打印消息,因此两条消息由不同的进程打印,因此,它们可以按任何顺序进行调度,因此子进程在父进程有机会打印谁是他的孩子。 这是完全正常的。

笔记

您必须注意fork()在出错时返回-1 ,它在布尔测试中评估为true ,就像父级的结果一样。 因此,如果您自由地将fork(2)的返回代码用于布尔表达式,则父级将收到truefork()失败时发生的任何错误(好吧,它们很少,但它们在加载的系统上是可能的)。 只需保存fork()的结果代码并首先检查错误,然后您就可以随意使用任何您想要的布尔表达式。

上面的源代码可以在这里下载

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM