【问题标题】:How Can I use fork() recursively?如何递归使用 fork()?
【发布时间】:2017-09-14 10:15:45
【问题描述】:

我一遍又一遍地对此进行编程,并且在学习如何使用 fork() 以递归方式生成子进程时遇到了麻烦。我开始编写一些非常复杂的东西,我决定用更简单的东西重新开始。

我刚开始学习流程,但在理解它们时遇到了困难。 该程序旨在分叉一棵进程树,但是,我必须从根分叉两个将分叉的进程,左侧是 3 个子进程,右侧是 4 个子进程。这些进程必须分别派生出它们自己的进程 3 和 4。

我对此的问题是该程序可以分叉进程,但是每一侧只有一个进程是各自一侧所有孩子的父亲。

你能给我的任何帮助都会很棒,如果我不够清楚,请告诉我。

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

/* Prototypes */
void three_children();
void four_children();

int main()
{
    pid_t process;
    int status,n;

    printf("Number of levels: \n");
    scanf("%d", &n);
    for (int i = 0; i < n ; i++) {
        process = fork();
        switch (process) {
            case -1:
                printf("Error\n");
                break;
            case 0:
                if (i == 0) {
                    printf("Left\n");
                    three_children(process, status);
                } 
                if (i == 1) {
                    printf("Right\n");
                    three_children(process, status);
                }
                printf("Hi I'm a child PID: %d, my father is PPID: %d\n", getpid(), getppid());
                exit(0);
            default:
                printf("I'm a father PPID: %d\n", getppid());
                break;
        }
    }
}

void four_children(pid_t process, int status)
{
    for (int j = 0; j < 4; j++) {
        process = fork();
        switch (process) {
            case -1:
                printf("Error\n");
                break;
            case 0:
                printf("I'm child: %d, and my father is: %d\n(four children)\n", getpid(), getppid());
                exit(0);
                break;
            default:
                printf("I'm a father process: %d\n", getpid());
                four_children(process, status);
                for (int j = 0; j < 3; j++) {
                    wait(&status);
                }
                break;
        }
    }
}

void three_children(pid_t process, int status)
{
    for (int k = 0; k < 3; k++) {
        process = fork();
        switch (process) {
            case -1:
                printf("Error\n");
                break;
            case 0:
                printf("I'm a child: %d, and my father is: %d\n(three children )\n", getpid(), getppid());
                exit(0);
                break;
            default:
                printf("I'm father %d\n", getpid());
                three_child(process, status);
                for (int j = 0; j < 3; j++) {
                    wait(&status);
                }
                break;
        }
    }
}

【问题讨论】:

  • cuatro_hijos = 4 个孩子,tres_hijos = 3 个孩子。
  • 当父级调用fork() 时,它会收到错误指示或子级的pid。在父级退出之前,它需要调用wait()(或者更好的waitpid())。如果父进程在所有子进程退出之前退出,那么这些子进程将成为“僵尸” 僵尸进程无法删除,除非重新启动计算机。每个父母都必须为该父母创建的每个孩子调用wait()(或waitpid()),
  • 在函数中:main(),变量status 在两个地方被传递给three_child(),但是它没有被初始化为任何特定的值并且因为它没有通过它的'地址,子功能无法更新它。这需要修复。否则代码包含未定义的行为。此外,status 并没有真正在任何地方使用,因此可以消除该参数以及 status 的声明
  • 没有人调用该函数:four_child(),因此发布的代码有一些“死代码”,并且发布的代码不符合 OPs 问题中的注释。
  • 函数:three_child()fork()生成的每个进程中调用three_child(),所以生成的进程数没有限制

标签: c unix process fork


【解决方案1】:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
typedef struct Node
{   
    int             childrenCount;
    struct Node*    child[0];
} Node;

Node* makeNode(int children)
{   
    Node* result = (Node*)malloc(sizeof(Node) + sizeof(Node*) * children);
    if (!result) {
        exit(1);
    }   
    result->childrenCount = children;
    for(int loop = 0;loop < children; ++loop) {
        result->child[loop] = NULL;
    }   
    return result;
}   

void buildTree(int indent, pid_t parent, Node* node);
void createChild(int indent, pid_t parent, Node* node, int childIndex)
{   
    pid_t pid = fork();
    if (pid == -1) {
        exit(1);
    }   
    if (pid == 0) {
        buildTree(indent + 1, getpid(), node->child[childIndex]);
        srand(parent * 10  + childIndex);
        exit(rand());
    }   
    for(int ind = 0; ind < indent; ++ind) {
        fprintf(stderr, " ");
    }   
    fprintf(stderr, "Parent: %d Spawned %d\n", parent, pid);
}   

void buildTree(int indent, pid_t parent, Node* node)
{   
    for(int ind = 0; ind < indent; ++ind) {
        fprintf(stderr, " ");
    }   
    fprintf(stderr, "Parent %d Has %d Children\n", parent, node->childrenCount);
    for(int loop = 0; loop < node->childrenCount; ++loop) {
        createChild(indent, parent, node, loop);
    }   
    for(int loop = 0; loop < node->childrenCount; ++loop) {
        int status;
        int child = wait(&status);
        for(int ind = 0; ind < indent; ++ind) {
            fprintf(stderr, " ");
        }
        fprintf(stderr, "Parent: %d Reaped %d with status %d\n", parent, child, status);
    }
}

int main()
{
    Node* root = makeNode(2);
    root->child[0]   = makeNode(3);
    for(int loopChild = 0;loopChild < 3; ++loopChild) {
        root->child[0]->child[loopChild] = makeNode(3);
        for(int loopGrandChild = 0;loopGrandChild < 3; ++loopGrandChild) {
            root->child[0]->child[loopChild]->child[loopGrandChild] = makeNode(0);
        }
    }
    root->child[1]   = makeNode(4);
    for(int loopChild = 0;loopChild < 4; ++loopChild) {
        root->child[1]->child[loopChild] = makeNode(4);
        for(int loopGrandChild = 0;loopGrandChild < 4; ++loopGrandChild) {
            root->child[1]->child[loopChild]->child[loopGrandChild] = makeNode(0);
        }
    }

    fprintf(stderr, "Start\n");
    buildTree(0, getpid(), root);
    fprintf(stderr, "Stop\n");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 2015-06-08
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多