进程中的fork(),wait()和exit()功能

问题描述 投票:1回答:1

我有如下所示的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)
       {
           printf("A");
       } else {
           process_id = wait(&status);
           printf("B");
       }
   } else {
       if (fork() == 0)
       {
           printf("C");
           exit(0);
       }
       printf("D");
   }
   printf("0");
   return 0;   
}

当我在终端中执行它时,在此图像中出现了一些输出:

some outputs for the source code written above

我实际上很困惑这些输出是如何生成的,例如,如何生成D0A0〜$ B0C。

谁能向我解释这些输出是如何生成的,以及在此代码中退出(0)吗?

c unix operating-system fork wait
1个回答
2
投票

通常,如果您有这样的代码

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()
                                   /    \
                ----  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”然后退出

  • 如您所见,这些过程的输出几乎可以任意交织,唯一的保证是在子父过程打印“ B0”之前,子子过程打印“ A0”。在主进程(父父进程)完成后,用于运行程序的Shell将重新获得控件。但是,当控件返回到Shell时,仍然可能有其他进程在运行,因此某些进程的输出可能会在Shell输出其命令提示符后出现。例如,以下事件链是可能的:

    • parent-parent获取控件。它显示“ D0”并退出,该控件返回到shell。

  • 子父进程获取控件。它开始等待(阻止)子进程。

  • 子进程获得控件。它显示“ A0”并退出。

  • 同时shell进程获取控件并打印命令提示符“〜$”

  • 父级进程得到控制。由于子进程已完成,因此将取消阻止,打印“ B0”并退出。

  • 父子进程获取控件,打印“ C”并退出。

  • 组合输出为“ D0A0〜$ B0C”。它说明了示例的最后一行。

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