【问题标题】:Why is the main process creating many children without loop?为什么主进程会创建许多没有循环的子进程?
【发布时间】:2015-10-12 22:40:19
【问题描述】:

我正在使用 Eclipse Luna IDE 在 Debian 发行版下使用 C 语言进行编程。

我的程序的主进程应该只执行一次,因此只创建3个子进程,然后在所有子进程结束后结束。

我看不出我的代码有什么问题,但我的程序创建了超过 3 个不同父亲的孩子。

有人可以告诉我如何获得预期的输出吗?

似乎主函数执行不止一次,但它没有循环来执行它。

这是我的代码:

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

int main(){

    pid_t IMU1_PID, IMU2_PID, IMU3_PID;

    IMU1_PID=fork();
    IMU2_PID=fork();
    IMU3_PID=fork();

    if (IMU1_PID<0 || IMU2_PID<0 || IMU3_PID<0) { perror("fork"); exit(errno);}

    if(IMU1_PID==0){
        printf("child1's PID: %d - father's PID: %d\n",getpid(),getppid());
        sleep(2);
        exit(0);
    }
    if(IMU2_PID==0){
        printf("child2's PID: %d - father's PID: %d\n",getpid(),getppid());
        sleep(2);
        exit(0);
    }
    if(IMU3_PID==0){
        printf("child3's PID: %d - father's PID: %d\n",getpid(),getppid());
        sleep(2);
        exit(0);
    }

    printf("PARENT %d waiting until all CHILDS end\n",getpid());
    while(wait(NULL)!=-1);
    printf("PARENT %d after all CHILDS ended\n",getpid());

    return 0;
}

这里是输出:

PARENT 4282 waiting until all CHILDS end
child3's PID: 4285 - father's PID: 4282
child2's PID: 4284 - father's PID: 4282
child2's PID: 4286 - father's PID: 4284
child1's PID: 4288 - father's PID: 4283
child1's PID: 4283 - father's PID: 4282
child1's PID: 4287 - father's PID: 4283
child1's PID: 4289 - father's PID: 4287
PARENT 4282 after all CHILDS ended

这是我所期望的:

PARENT 4282 waiting until all CHILDS end
child3's PID: 4285 - father's PID: 4282
child2's PID: 4284 - father's PID: 4282
child1's PID: 4288 - father's PID: 4282
PARENT 4282 after all CHILDS ended

【问题讨论】:

  • 为什么你认为“我的程序的主进程应该只执行一次......”?根据定义,当您 fork 时,fork() 的函数的其余部分(在本例中为 main)在原始进程和新创建的进程中都执行。
  • 谢谢!起初我无法理解你,但现在我明白了。

标签: c multithreading concurrency fork


【解决方案1】:

使用 Erik Eidt 的话“当您 fork 时,根据定义,fork()(在本例中为 main)在原始进程和新创建的进程中执行的函数的其余部分。”

正如 Charles 所写,我之前的代码在第二次或第三次调用 fork() 之前没有检查 pid!初始进程调用第一个fork(),然后父进程和第一个子进程都调用第二个fork(),然后原始进程和两个子进程中的每一个都会调用第三个fork()

所以下面是正确的代码:

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

int main(){

    pid_t IMU1_PID, IMU2_PID, IMU3_PID;

    IMU1_PID=fork();
    if (IMU1_PID<0) { perror("fork"); exit(errno);}
    if(IMU1_PID==0){
        printf("child1's PID: %d - father's PID: %d\n",getpid(),getppid());
        sleep(2);
        exit(0);
    }

    IMU2_PID=fork();
    if (IMU2_PID<0) { perror("fork"); exit(errno);}
    if(IMU2_PID==0){
        printf("child2's PID: %d - father's PID: %d\n",getpid(),getppid());
        sleep(2);
        exit(0);
    }

    IMU3_PID=fork();
    if (IMU3_PID<0) { perror("fork"); exit(errno);}
    if(IMU3_PID==0){
        printf("child3's PID: %d - father's PID: %d\n",getpid(),getppid());
        sleep(2);
        exit(0);
    }

    printf("PARENT %d waiting until all CHILDS end\n",getpid());
    while(wait(NULL)!=-1);
    printf("PARENT %d after all CHILDS ended\n",getpid());

    return 0;
}

【讨论】:

    【解决方案2】:

    正如fork() 的手册页中明确解释的那样,函数 1) 如果失败返回 -1,2) 如果成功,则返回父进程中的两个不同进程(每个进程都运行原始代码。),返回value 是子进程的pid。在子进程中,返回值为 0。发布的代码未检查返回值,因此父进程和子进程都在执行对 fork() 的任何后续调用。

    建议检查返回的值并让代码正确运行。

    例如:

    pid1 = fork();
    if( pid1 <0 ) {handle error and exit}
    if( pid1 ==0 ) { processing for child1 and exit}
    // if got here then parent
    pid2 = fork();
    if( pid2 <0 ) { handle error and exit }
    if( pid2 == 0) { processing for child2 and exit }
    // if got here then parent
    etc.
    

    【讨论】:

    • 抱歉,我看不出我们的逻辑有什么区别。你写的正是我写的。
    • if(pidx == 0) 中的所有内容都是 pidx 的所有者例程,而 if 之外的所有内容都是父亲的例程
    • @CleberMarques,您的代码在第二次或第三次调用 fork() 之前不会检查 pid!您的初始进程调用第一个 fork(),父进程和第一个子进程都调用第二个 fork(),原始进程和 3 个子进程中的每一个都将调用第三个 fork()。
    • @CharlesE.Grant,Tks,现在我明白了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    相关资源
    最近更新 更多