Fork() 子链

Fork() Child Chain

我有以下代码,它使用 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;

}

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

Hello World! Greetings from PID: 118358! :D
Hello World! Greetings from PID: 118359! :D
Hello World! Greetings from PID: 118360! :D
Hello World! Greetings from PID: 118362! :D

我想要做的是让父进程创建一个子进程,而不是让 1 个父进程有多个子进程,子进程创建一个子进程,依此类推定义的线程数。我该怎么做?

您的示例代码使用 fork() 的 return 值来区分 parent 和 child。它继续在 parent 中迭代(假设 fork() 没有报告错误),并且它 exit() 没有在 child 中迭代(在发出一些输出之后)。这完全是例行公事。

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

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

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

关键是每个 child 都会得到它的 parent 变量的副本,所以如果 child 更新一个计数变量,然后分叉,新的 child 将看到更新后的计数。

首先,您使用的术语 "thread" 在这种情况下是不合适的。 Fork 表示 "creating process" 而不是 "threads".

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

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

#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