【问题标题】:Fork() Child ChainFork() 子链
【发布时间】:2016-10-19 15:46:18
【问题描述】:

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

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

#define NUM_THREADS     4

int main()
{
        int i;
        pid_t pid;
        for(i = 0; i < NUM_THREADS; i++){ //Do this equal to the number of threads
            pid = fork();//Use this to avoid multiple forking

            if(pid == 0){ //If it's a child process
                    printf("Hello World! Greetings from PID: %ld! :D\n", (long)getpid()); //getpid returns the pid of the process
                    exit(0); //Exit the process
            }else if(pid == -1){
                    printf("Oh no! Could not fork! :( Exiting!\n");
                    return 0;
            }
    }
    int status;
    for(i = 0; i < NUM_THREADS; i++){
            wait(&status);//wait until all the children processes have finished.
    }
    printf("All done! I am the parent process! My PID is: %ld if you were curious! \n", (long)getpid());

    return 0;

}

这是作为示例提供给我们的。 它的输出是这样的:

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

我想做的是让父进程创建一个子进程,然后再创建一个子进程,而不是让 1 个父进程和许多子进程,以此类推,以定义线程数。我该怎么做?

【问题讨论】:

  • 您是否尝试过自己编写代码?你到底有什么问题?

标签: c fork wait


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    1. 打印它的消息
    2. 更新计数变量,如果计数小于最大值
    3. 分叉一个新的孩子
    4. 等待它的孩子

    关键是每个子节点都会得到其父变量的副本,因此如果子节点更新计数变量,然后分叉,新子节点将看到更新后的计数。

    【讨论】:

    • 当然可以递归实现所需的行为,但任何递归算法都可以转换为迭代算法(不改变可观察的行为),反之亦然。因此,解决方案是迭代还是递归似乎是一个红鲱鱼。
    • 嗯,在一个更现实的程序中,如果将子进程创建为一个链,调用函数可能比循环更自然,因为每个进程都有一个有意义且不同的目的。
    【解决方案3】:

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

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

    这是一个运行良好的简单代码:

    #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;
    }
    

    See output

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-19
      • 2021-06-07
      • 2018-03-05
      • 2021-04-28
      • 1970-01-01
      相关资源
      最近更新 更多