【问题标题】:Why there are many PIDs printed while using fork system call?为什么在使用 fork 系统调用时会打印很多 PID?
【发布时间】:2013-10-19 20:22:51
【问题描述】:

我正在学习 Linux 中的进程管理,并尝试实现以下 C 程序,其输出打印了 15 个 PID(4 个唯一 PID)。我试图弄清楚进程家族树,但它真的没有帮助我理解为什么 PID 被打印了这么多次。我浏览了几个链接,包括http://u.cs.biu.ac.il/~linraz/os/OS2.pdfhttp://www.ibm.com/developerworks/aix/library/au-unixprocess.htmlWho executes first after fork(): parent or the child?。但是,我找不到解决方案。如果有人帮助我理解这个问题,那将是非常有帮助的。

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

    int main()
    {
           printf ( "Parent:%d Child: %d\n",getppid(),getpid()); // To print the PIDs of the parent process and the child process
           fork();               //System call to spawn a child process
           printf ( "Parent:%d Child: %d\n",getppid(),getpid()); 
           fork();
           printf ( "Parent:%d Child: %d\n",getppid(),getpid());
           fork();
           printf ( "Parent:%d Child: %d\n",getppid(),getpid());
           return 0;
    }

【问题讨论】:

  • 只是要明确一点,(1)父母或孩子是否先运行(甚至同时)是完全不确定的。这仅取决于操作系统当时如何安排它们。 (2) 你写的程序可能会给出一些误导性的结果。取决于他们是如何死的,因为你不看孩子,许多 printfs 将显示init(进程 pid 1)作为他们的父母,因为他们已经是僵尸。

标签: c operating-system fork


【解决方案1】:

每次调用 fork 时,您都在复制当前进程。所以第一个 printf 执行一次——只有一个进程。然后您调用fork(),以便第二个 printf 执行两次——一次在父进程上,一次在新子进程上。然后父子每个fork共创建4个进程,等等……

【讨论】:

    【解决方案2】:

    当您fork 时,会创建一个新进程,但父进程也会继续执行。所以你的main 将执行所有 4 次打印,你的第一个 fork 将执行随后的 3 次打印,依此类推。要控制每个子级和父级将执行的代码,您必须使用 fork 返回值,而不仅仅是 fork。

    【讨论】:

      【解决方案3】:

      当您的程序启动时,内核会为其分配一个 PID。 PPID 是启动程序的进程的 PID,通常是你的 shell。出于此答案的目的,我们将为您的 shell 分配 123 的 PID,并且您的程序在开始时将分配为 130 的 pid。

      输出的第一行将简单地显示 PPID 和 PID。

      Parent:123 Child: 130
      

      程序接下来要做的就是将自己一分为二。原程序的PID和PPID不变,子程序的PPID就是原程序的PID,给子程序分配一个新的PID。由于两个程序仍然绑定到相同的输出通道,因此可以先显示任何一个的输出。为简单起见,我们假设输出是有序的。

      Parent:123 Child: 130
      Parent:130 Child: 131
      

      现在你第二次分叉了……两个进程复制自己。您现在有四个进程想要将输出打印到同一通道。

      Parent:123 Child: 130
      Parent:130 Child: 131
      Parent:130 Child: 132
      Parent:131 Child: 133
      

      现在,通过您的第三个分叉,所有这四个进程都会再次复制自己。

      Parent:123 Child: 130
      Parent:130 Child: 131
      Parent:130 Child: 132
      Parent:131 Child: 133
      Parent:130 Child: 134
      Parent:131 Child: 135
      Parent:132 Child: 136
      Parent:133 Child: 137
      

      有什么问题吗?

      【讨论】:

        【解决方案4】:

        fork() 通过复制调用进程来创建一个新进程。新进程,称为子进程,与调用进程完全相同, 称为父级。

        A fork() 
        |----------------B
        |                |   
        |fork()          |
        |----C           |
        |    |           |
        

        如果你调用 fork(),下一条指令将由子进程和父父进程执行

        你的程序是这样的

               printf ("Hi"); //prints only one time   
               fork();
               printf ("Hi"); //prints two times
               fork();
               printf ("Hi"); //prints four times 
        

        考虑所有fork()成功创建的子进程。

               printf ("Hi"); 
               fork();------------------------------------------------|
                  |                                                   | 
               printf ("Hi");                                       printf ("Hi"); 
               fork();----------------|                             fork();---------------|
               printf ("Hi");      printf ("Hi");                   printf ("Hi");        printf ("Hi"); 
        

        【讨论】:

        • 插图非常精美。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-10
        • 2017-07-25
        • 2018-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多