我正在尝试更好地理解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()之后的代码在子进程中的代码之前执行?
答案 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);