我正在执行下面的代码,并且对 waitpid()
的调用始终返回 -1
,因此下面的代码以无限循环结束。如果我将 WNOHANG
替换为 0
,则调用可以正常工作。
void execute(cmdLine* pCmdLine) {
int status = 0;
pid_t pid = fork();
if(pid == 0) {
if(execvp(pCmdLine->arguments[0], pCmdLine->arguments) == -1) {
if(strcmp(pCmdLine->arguments[0], "cd") != 0) {
perror("execute failed\n");
}
_exit(1);
}
} else {
if(pCmdLine->blocking == 1) {
waitpid(pid, &status, 0);
}
while(waitpid(pid, &status, WNOHANG) == -1) {
printf("still -1\n");
}
}
}
}
最佳答案
好吧,你误解了 wait
的工作原理系统调用。
与malloc/free
一样,你只能成功waitpid()
每个 fork()
仅一次编辑过程...所以 while
如果您要等待子级的退出代码,则永远不需要循环,只需调用它一次。等待将仅返回 -1
在你的情况下,有两个原因:
-
fork()
没有成功,所以您正在等待无效的pid
。事实上,您应该调用wait()
对于pid == -1
,这是无效的。万一你wait()
并且没有要等待的进程(如果pid
变量具有正数,但对于已经wait()
ed 子进程,您还会得到-1
),您会从任何wait()
中收到错误系统调用家族。 UN*X 系统中僵尸进程的使命就是这样,以确保wait()
对于已经完成的子进程仍然有效,并且调用进程获取子进程在exit()
上发出的退出代码信号。 . 您明确表示您不会等待该过程完成。应该清楚的是,如果您不打算等待进程终止,那么这就是您对
WNOHANG
所做的事情。参数,那么子进程仍然可以运行(这是你的情况)并且尚未完成exit()
系统调用。您只需要退出代码以防子进程已经完成。如果是这种情况,那么你最好这样写:while(waitpid(pid, &status, WNOHANG) == -1 && errno == EAGAIN) do_whatever_you_want_because_you_decided_not_to_wait();
wait
系统调用无法告诉您&status
变量尚未填充子进程的退出代码而不是发出错误信号,在这种情况下,它始终设置errno
至EAGAIN
。但是,从我的角度来看,如果你同时没有什么可做的,那么你最好不要使用
WNOHANG
。这将节省 CPU 周期并减少向环境排放的大量热能。
关于c - `waitpid()' 始终返回 -1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55785052/