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

时间:2017-06-08 18:22:19

标签: 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
    }
}

控制台输出:

$ ./waitpidexample 
[6103] Hi I am the parent and I am about to create a child...
Error: No child processes
[6103] 1540418008
[6103] value returned by waitpid: -1
[6103] child killed (signal 54)
[6104] 6285
[6104] Hi, I am the child process...
[6104] 0
[6104] 1
[6104] 2

我相信我的问题在于waitpid()...

中使用的cPID变量

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

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

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

2 个答案:

答案 0 :(得分: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;
}

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

运行订单

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

答案 1 :(得分:2)

在父进程中,永远不会初始化cPID。父级和子级中的变量彼此分开,因此子级中的变量更改在父级中不可见,反之亦然。

父母已在childPID中拥有子pid,因此请改用它。

printf("[%i] %i\n", getpid(), childPID );
wPID = waitpid(childPID, &status, 0);