Fork() 代码未按预期工作 - 层次结构制作

Fork() code not working as expected - Hierarchy making

下午好。

我目前正在开发一个 C 程序,该程序采用一个且只有一个参数,该参数指定要创建的 "child generation" 的数量(自己的父亲已经算作 1 个)。 "wait()" 系统调用不用于此练习(具有 "wait" 调用的版本恰好按预期工作)。

例如,调用 $program 4 应该生成如下层次结构: 进程 A 创建 B 进程 B 创建 C 进程 C 创建 D

打印的消息并不重要,因为它们只是任务的方向。使用以下代码(恰好通过 "wait()" 调用完全按照我想要的方式工作)表明所有子进程都来自同一个父亲,我不明白为什么会这样。

#include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>

    int main(int argc, char *argv[]) {
    int counter; pid_t result; int i;

    /*
    We are going to create as many processes as indicated in argv[1] taking into account that the main father already counts as 1!
    */
    if (argc > 2 || argc == 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
    int lim = atoi(argv[1]);


    //We eliminate the impossible cases
    if (lim < 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}


    if (lim == 1) {puts("The father himself constitutes a process all by his own, therefore:\n");
    printf("Process%d, I'm %d and my father: %d\n", counter, getpid(), getppid());
     }
    else {
        for (i = 0; i < lim; i++) {
            result = fork();
            if (result < 0) {
                printf("Call%d \n", counter); perror("Has failed!");
                exit(-1);
            }
            else if (result) {
                break; //Father process
            }
            else {
                counter++;    //Child processes increment the counter
                printf("Process%d, I am %d and my father: %d\n", counter, getpid(), getppid());
            }
        }
    }

上面代码生成的层次结构不是我预期的...

非常感谢所有帮助。 谢谢

With the following code (which happens to work exactly how I want with a "wait()" call) states that all the child processes derive from the same father, which I don't understand why it's happening.

我在测试中没有看到这一点,我也没有任何理由期望您确实是这种情况。但是,如果您看到的是部分或全部 child 进程将进程 1 报告为它们的 parent,那么您可能 看起来 就是这种情况。如果他们原来的 parent 在 child 的 getppid() 调用被处理之前终止,就会发生这种情况。以这种方式孤立的进程继承进程 1 作为它们的 parent。如果 child 的 parent wait() 先终止,那么这种情况就不会发生,但是如果 parent 在分叉 child 之后很快终止,那么结果是完全合理的。

这是您的循环的一个变体,它将在每种情况下报告原始 parent 进程 ID:

    pid_t my_pid = getpid();

    for (i = 0; i < lim; i++) {
        result = fork();
        if (result < 0) {
            printf("Call%d \n", counter); perror("Has failed!");
            exit(-1);
        } else if (result) {
            break; //Father process
        } else {
            pid_t ppid = my_pid;  // inherited from the parent
            my_pid = getpid();
            counter++;    //Child processes increment the counter
            printf("Process%d, I am %d and my father: %d\n", counter, (int) my_pid, (int) ppid);
        }
    }

你错过了一个关键的函数调用。

    for (i = 0; i < lim; i++) {
        fflush(stdout);             // <============== here
        result = fork();

没有它,您的 fork 会将父进程的标准输出缓冲区复制到子进程中。这就是您看到父进程输出重复多次的原因 --- 它的子进程和孙进程继承了输出缓冲区。

Live demo(格式固定,方便阅读)。