使用Fork()创建所需的进程数

时间:2015-11-18 10:38:28

标签: c

我正试图绕过系统调用fork(),我想创建尽可能多的孙子进程。基本上我想要实现的是:

1个父进程 - > 2个子进程 - >每个孩子 - >有两个子进程(总共有4个来自父进程的孙进程)。

              parent
          /           \
         /             \
    child1             child2
    /    \               /  \
   /      \             /    \
  /        \           /      \
g.child1  g.child2  g.child3  g.child4

到目前为止,我可以从4个孙子中得到3个,但我也是从一个孙子中得到一个新孩子。这是我到目前为止的输出:

Process Pid: 5960 PPid: 5958 (position: 1).
Process Pid: 5959 PPid: 5958 (position: 0).
Process Pid: 5962 PPid: 5959 (position: 0).
Process Pid: 5961 PPid: 5960 (position: 1).
Process Pid: 5963 PPid: 5961 (position: 1).
Process Pid: 5964 PPid: 5960 (position: 1).

任何提示?

谢谢

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

#define NUM_HIJOS 2 

void lanzanieto(int i)
{
    int proceso;

    proceso = fork();
        if (proceso > 0) {
                wait(NULL);
        } else if (proceso == 0) {
            printf("Process Pid: %d PPid: %d (position: %d).\n",getpid(),getppid(), i);
        } else if (proceso == -1) {
            perror("fallo en fork");
            exit(EXIT_FAILURE);
        }
}
int main(void)
{
    int proceso, i;

    for (i=0; i<NUM_HIJOS; i++) {
        proceso = fork();

        if (proceso == 0) {

            switch(i) {
                case 0:
                    printf("Process Pid: %d PPid: %d (position: %d).\n",getpid(),getppid(), i);
                    lanzanieto(i);
                    exit(0);
                case 1:
                    printf("Process Pid: %d PPid: %d (position: %d).\n",getpid(),getppid(), i);
                    lanzanieto(i);
                    lanzanieto(i);
                    exit(0);        
            }

        }  else if (proceso == -1) {
            perror("fallo en fork");
            exit(EXIT_FAILURE);
        }

    }
    proceso = wait(NULL);
    while (proceso > 0) {
        proceso = wait(NULL);
    }
    /* ************************************* */
    if (proceso == -1 && errno != ECHILD) {
        perror("fallo en wait");
        exit(EXIT_FAILURE);
    }
}

2 个答案:

答案 0 :(得分:4)

概念

首先,创建fork()将如下所示:

id = fork(); 
if (id < 0) {
    /* error */
    exit(1);
} 
else if (i > 0) { /* Parent > 0 */
    /* parent logic */
} 
else { /* Child = 0 */
    /* child logic */
}

fork()将在父进程旁边创建一个子进程。

因此,如果您想匹配您的树(并且基于您现有的代码),流程图将如下所示:

parent : fork()
           |--> parent : fork()
           |               |--> parent
           |               |--> child_2
           |
           |--> child_1 : fork()
                           |--> child_1
                           |--> sub_child_1

简而言之,您必须在父级和每个新子进程内递归fork()

然而,承认分叉过程并不好看。

拥有一个函数可能会更好,让我们说create_child(),它只从父级派生:

parent : create_fork()
               |--> parent : create_child()
               |        |
               |        |--> parent : create_child()
               |        |      |
               |        |      |--> parent 
               |        |      |--> child_3 : do_whatever()
               |        |
               |        |--> child_2 : do_whatever()
               |        
               |--> child_1 : do_whatever()

解决方案

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

void print_pid(char *proc_name)
{
    printf("%s: %d\n", proc_name, getpid());
}

int create_child(void)
{
    pid_t child_pid = fork();
    if (child_pid == 0)
    {
        print_pid("child");
    }
    else if (child_pid < 0)
    {
        perror("create_child");
    }
    return (child_pid);
}

int make_babies(int babies_number)
{
    /* if no baby */
    if (babies_number <= 0)
        return 0;

    /* if baby(ies) */
    pid_t child_pid = create_child();
    if (child_pid > 0)
    {
        make_babies(babies_number - 1);
        waitpid(child_pid, NULL, 0);
    }
    return child_pid;
}

int main(void)
{
    print_pid("parent");
    make_babies(50);
    return errno;
}

答案 1 :(得分:1)

您必须记住子进程和父进程都继续执行相同的代码。当您在lanzanieto(i)的{​​{1}}内拨打case 1:两次时,父母和孩子从第一次拨打main()(原始父母的孩子和孙子)继续第二次打电话给lanzanieto(i),这样两个人都会产生另一个孩子。