【问题标题】:Controlling Forks in C在 C 中控制分叉
【发布时间】:2009-08-06 13:00:47
【问题描述】:

我有一个如下所示的 C 文件:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
int main () 
{ 
    pid_t child_pid; 
    printf ("The PID is %d\n", (int) getpid ()); 
    child_pid = fork (); 
    if (child_pid != 0)
    { 
        printf ("this is the parent process, with PID %d\n", 
        (int)getpid()); 
        printf ("the child's PID is %d\n", (int) child_pid); 
    } 
    else 
        printf ("this is the child process, with PID %d\n", 
        (int)getpid()); 
    return 0; 
} 

我需要修改它以生成一个看起来像这样的层次结构

parent (0)
  |
  +---> child (1)
  |
  +---> child (2)
          |
          +----> child (3)
          |
          +----> child (4)
                  |
                  +----> child (5)
                  |

基本上是一个树结构,其中每个第二个孩子产生两个新孩子。据我了解,当我fork()一个进程时,每个进程都会同时运行。在if 语句中添加fork() 似乎可以正常工作并正确创建进程0 到2,因为只有父进程会创建一个新的fork。但我不知道如何制作流程 2 的 fork 而不是 1。有什么想法吗?

【问题讨论】:

  • 你考虑过这个过程的限制吗?什么时候停止,为什么?它将对操作系统做什么? (在 unix 派生系统上,请考虑阅读 ulimit 的手册页。)只是想提供帮助。

标签: c tree fork


【解决方案1】:

那么,进程 1 将由第一个分叉创建。进程 2 将由 if 语句中的 fork 创建。所以要让进程 2 也分叉,如果第二个分叉没有返回 0,则在 if 语句中再次分叉。

插图:

if(fork) {
    // Inside process 0
    if(fork) {
        // still in process 0
    } else {
        // in process 2
        if(fork) {
          // still in process 2
        } else {
          // in prcess 3
        }
        // and so on
    }
} else {
    // Inside process 1
}

【讨论】:

    【解决方案2】:

    孩子在分叉时获得父母状态的副本。

    因此,如果父级具有计数器或其他属性,则子级将在它们被分叉时看到该值(但如果父级随后更改它,则不会看到)。

    【讨论】:

      【解决方案3】:

      我不知道你为什么要这样做,但通常只有父进程执行分叉。这也可能更容易设计。当您在 for 循环中执行 fork() 时,您将可以直接控制创建的进程。

      请注意 fork() 是一个相对昂贵的操作,尤其是如果您想创建许多进程。有更轻量级的替代品 vfork 和线程可用,但我无法判断它们是否也符合您的需求。

      【讨论】:

      • 任何进程都可以分叉,甚至是子进程。事实上,这就是分叉炸弹的编写方式,每个进程分叉另外两个,直到系统被淹没。
      • 这只是一个练习——我绝不会心甘情愿地做这么奇怪的事情:)
      【解决方案4】:

      一个老问题,但仍然很有趣。 man page for fork() 告诉我们返回值:

      成功时,父进程返回子进程的PID,子进程返回0。失败时,在父进程中返回 -1,不创建子进程,并适当设置 errno。

      所以我们知道fork()返回一个0给孩子,我们可以用它作为控制机制:

      int main()
      {
         // Here we're in the parent (0) process
      
         if(fork())  // This starts the chain, only the parent will do this
          if(!fork()) //the child will pass this, the parent will skip it
           for(count = 0; counter < number_of_processes; counter++) //now the 2nd child loops
           {
               if(fork())
                   if(!fork());
               else
                   break;
           }
      

      让我们给它一些数字:

      //parent (18402)
      if(fork()) // spawns 18403, parent 18402 keeps going
        if(!fork()) // spawns 18404, parent 18402 drops to the end of main()
          for(count = 0; count < number_of_processes; conter++) // 18404 enters here
            if(fork())  // 18404 forks 18405 and then goes on
              if(!fork());  // 18404 spawns 18406 before leaving, 18406 restarts the loop
              else
                break; // 18404 breaks out there
            else
                break; //18405 leaves the loop here
      

      所以在一次迭代之后,我们有:

        18402
          |
          +---> 18403
          |
          +---> 18404
                  |
                  +----> 18405
                  |
                  +----> 18406
                           |
      

      在此之后,我们将继续循环两个新进程,其中第二个进程将继续迭代,直到您完成所需次数为止。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-26
        • 1970-01-01
        • 2015-05-29
        • 2017-10-09
        • 2011-04-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多