首页 > 解决方案 > `waitpid()' 总是返回 -1

问题描述

我正在执行下面的代码并且调用waitpid()always 返回-1,因此下面的代码以无限循环结束。如果我WNOHANG0.

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");
            }
         }     
    }
}

标签: clinuxunixwaitpid

解决方案


好吧,您误解了wait系统调用的工作原理。

与 一样,每个ed 进程malloc/free只能成功waitpid()一次...因此,如果您要等待子进程的退出代码,则永远不需要循环,您只需调用它一次。Wait只会在您的情况下返回,原因有两个:fork()while-1

  • fork()没有成功,所以你在等待一个 invalid pid。确实,您应该呼吁wait()pid == -1这是无效的。如果您wait()并且没有要等待的进程(如果pid变量具有正数,但对于已经wait()ed 的子进程,您也会得到),您会从任何系统调用系列中-1得到一个错误。UN*X 系统中僵尸wait()进程的任务就是这样,确保已经完成的子进程的 a 仍然有效,并且调用进程得到子进程 on 发出的退出代码。wait()exit()
  • 您明确表示您不会等待该过程完成。应该清楚的是,如果您不打算等待进程终止,这就是您正在使用WNOHANG参数执行的操作,那么子进程可以仍在运行(这是您的情况)并且尚未完成exit()系统调用。如果子进程已经完成,您只需要退出代码。如果是这种情况,那么你最好写:

    while(waitpid(pid, &status, WNOHANG) == -1 && errno == EAGAIN)
        do_whatever_you_want_because_you_decided_not_to_wait();
    

    wait系统调用没有办法告诉您该变量&status没有被子进程的退出代码填充,而是发出错误信号,在这种情况下,它总是设置errnoEAGAIN.

    但是,从我的角度来看,如果您在此期间无事可做,那么您最好不要使用WNOHANG. 这将节省 CPU 周期和大量释放到环境中的热能。


推荐阅读