C Fork()子链

C Fork()子链,c,fork,wait,C,Fork,Wait,我有以下代码,它使用fork()创建定义数量的子线程: #包括 #包括 #包括 #包括 #包括 #包括 #定义NUM_线程4 int main() { int i; pid_t pid; 对于(i=0;i

我有以下代码,它使用
fork()
创建定义数量的子线程:

#包括
#包括
#包括
#包括
#包括
#包括
#定义NUM_线程4
int main()
{
int i;
pid_t pid;
对于(i=0;i
}

这是作为一个例子提供给我们的。 其输出如下:

世界你好!来自PID:118358!的问候语:D
你好,世界!来自PID:118359!的问候语:D
你好,世界!来自PID:118360!的问候语:D
世界你好!来自PID:118362!D!的问候


我想做的是让父进程创建一个子进程,而不是让一个父进程有许多子进程,这样子进程就可以为定义的线程数创建一个子进程,依此类推。我怎么做呢?

您的示例代码使用
fork()的返回值
来区分父级和子级。它继续在父级中迭代(假设
fork()
没有报告错误),并且它
exit()
s没有在子级中迭代(在发出一些输出后)。这是完全例行的


你建议做的并没有太大的不同;你描述的主要只是交换了父级和子级的角色。事实上,你有一个更简单的工作,因为每个父级只需要为一个子级
wait()
。它可以在循环内部或外部执行,前提是如果最后一个子级
wait()
s然后它应该期望调用指示错误,因为该子级没有自己的子级。如果父级没有
exit()
从循环内部返回
,但它确实需要中断而不是进一步迭代。

此任务与将迭代解决方案转换为递归解决方案相同。第一步是删除
for
循环。然后修改子代码,使每个子代码:

  • 打印其消息
  • 更新计数变量,如果计数小于最大值
  • 叉出一个新的孩子
  • 等待它的孩子
  • 关键是每个子级都会获得其父级变量的副本,因此,如果子级更新计数变量,然后分叉,新的子级将看到更新的计数。

    首先,您使用的术语“线程”在这种情况下是不合适的。 Fork的意思是“创建进程”,而不是“线程”

    您可以使用递归解决方案,但您必须记住,创建流程的每个流程都应该等待返回状态,以避免僵尸流程。在流程之间不使用任何共享变量的情况下,您可以使用单个变量计数器,每个分叉都会递增。但一旦计数器变量达到最大值,则e“最年轻的”进程,我的意思是创建的最后一个进程应该退出,而另一个进程将逐个退出

    下面是一个简单的代码,可以很好地工作:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define NUM_PROCESS 5
    
    int counter = 0;
    
    void child_func() 
    {
        pid_t pid;
    
        if (counter < NUM_PROCESS) {
    
            counter++;
    
            pid = fork();
    
            if (pid < 0) {
    
                printf("fork failed counter = %d\n", counter);
    
            }
            else if (pid == 0) {
    
                printf("Hello world ! Greetings from pid %ld\n", (long)getpid());
    
                if (counter == NUM_PROCESS) {
                    exit(0);
                }
                else {
                    child_func();
                }
            }
            else {
    
                long var  = pid;
    
                wait(&pid);
    
                printf("My pid is %ld and i am the parent of %ld child, i exit\n", (long)getpid(), var);
    
                exit(0);
            }   
        }
    }
    
    int main(void) 
    {
    
        pid_t pid;
    
        pid = fork();
    
        if (pid < 0) {
    
            printf("Fork failed %d\n", counter);
    
            return -1;
        }
    
        if (pid == 0) {
    
            child_func();
        }
        else {
    
            wait(&pid);
        }
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    #定义NUM_进程5
    int计数器=0;
    void child_func()
    {
    pid_t pid;
    if(计数器

    当然可以递归地实现所需的行为,但任何递归算法都可以转化为迭代算法(不改变可观察的行为),反之亦然。因此,解决方案是迭代的还是递归的似乎是一个模糊的问题。好吧,在一个更现实的程序中,如果子对象被创建为一个链,调用函数可能比循环更自然,因为每个过程都有一个有意义和不同的目的。您是否尝试过自己编写此代码?您到底在做什么有麻烦吗?
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define NUM_PROCESS 5
    
    int counter = 0;
    
    void child_func() 
    {
        pid_t pid;
    
        if (counter < NUM_PROCESS) {
    
            counter++;
    
            pid = fork();
    
            if (pid < 0) {
    
                printf("fork failed counter = %d\n", counter);
    
            }
            else if (pid == 0) {
    
                printf("Hello world ! Greetings from pid %ld\n", (long)getpid());
    
                if (counter == NUM_PROCESS) {
                    exit(0);
                }
                else {
                    child_func();
                }
            }
            else {
    
                long var  = pid;
    
                wait(&pid);
    
                printf("My pid is %ld and i am the parent of %ld child, i exit\n", (long)getpid(), var);
    
                exit(0);
            }   
        }
    }
    
    int main(void) 
    {
    
        pid_t pid;
    
        pid = fork();
    
        if (pid < 0) {
    
            printf("Fork failed %d\n", counter);
    
            return -1;
        }
    
        if (pid == 0) {
    
            child_func();
        }
        else {
    
            wait(&pid);
        }
    
        return 0;
    }