调用waitpid()的父进程无法找到其子进程

cbl*_*to7 0 c

我试图更好地了解fork(),waitpid()和子进程/父进程,但是以下代码遇到一些奇怪的行为:

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

int main(void){ // Main

    int status;
    pid_t wPID, cPID;
    printf("[%i] Hi I am the parent and I am about to create a child...\n", getpid());
    fflush(0); 
    pid_t childPID = fork();

    if (childPID >= 0){
        if(childPID == 0){ //child process
            cPID = getpid();
            printf("[%i] %i\n", getpid(), cPID );
            printf("[%i] Hi, I am the child process...\n", getpid() );
            sleep(1);

            for(int i = 0; i<3; i++){
                printf("[%i] %i\n", getpid(), i);
            }
            exit(0);
        }
        else{ //parent
            printf("[%i] %i\n", getpid(), cPID );
            wPID = waitpid(cPID, &status, 0);
            printf("[%i] value returned by waitpid: %i\n", getpid(), wPID);

            if (WIFEXITED(status))
                printf("[%i] child exited, status=%d\n", getpid(), WEXITSTATUS(status));
            else if (WIFSIGNALED(status))
                printf("[%i] child killed (signal %d)\n", getpid(), WTERMSIG(status));
            else if (WIFSTOPPED(status))
                printf("[%i] child stopped (signal %d)\n", getpid(), WSTOPSIG(status));
            else  /* Non-standard case -- may never happen */
                printf("Unexpected status (0x%x)\n", status);
            return 0; 
        }
    }
    else{
        printf("\n Fork failed, quitting!\n");
        return 2;  // error
    }
}
Run Code Online (Sandbox Code Playgroud)

控制台输出:

$ ./waitpidexample 
[6103]嗨,我是父母,我即将创建一个孩子...
错误:没有子进程
[6103] 1540418008
[6103] waitpid返回的值:-1
[6103]儿童被杀(信号54)
[6104] 6285
[6104]嗨,我是孩子进程...
[6104] 0
[6104] 1
[6104] 2

我相信我的问题是在waitpid()中使用了cPID变量...

这里会发生某种范围问题,因为它会评估子项/父项中的不同值。

我应该如何获取在waitpid()中使用的正确子进程ID?

为什么在waitpid()之后的代码在子进程中的代码之前执行?

Jam*_*ert 5

cPID仅在子进程中更改。当您调用fork时,将创建完整的副本(实际上,实际上是在更改某些内容之前,共享内存)。这意味着当cPID写入子级(第一个分支)时,父级看不到它。cPID将父级(第二个分支)中对的引用更改为childPID(从分配fork()):

else{ //parent
    printf("[%i] %i\n", getpid(), childPID );
    wPID = waitpid(childPID, &status, 0);
    printf("[%i] value returned by waitpid: %i\n", getpid(), wPID);
    if (WIFEXITED(status))
        printf("[%i] child exited, status=%d\n", getpid(), WEXITSTATUS(status));
    else if (WIFSIGNALED(status))
        printf("[%i] child killed (signal %d)\n", getpid(), WTERMSIG(status));
    else if (WIFSTOPPED(status))
        printf("[%i] child stopped (signal %d)\n", getpid(), WSTOPSIG(status));
    else  /* Non-standard case -- may never happen */
        printf("Unexpected status (0x%x)\n", status);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

另外,我建议在所有if语句后都使用大括号

运行订单

fork()并没有定义首先运行哪个进程,只是现在有一个子进程(在其中返回0)和一个父进程(在其中返回孩子的PID)。子进程将与父进程相同,但返回值为fork()。有时,父母先走,有时孩子先走。它是不确定的。