fork - 我可以退出 parent 吗?

fork - Can I exit from parent?

我编写了一个代码,它将调用 exec,如下所示。但是如果我从 main 调用 isValid,child 和 parent 进程都在 returning 并且我得到了两次输出。

我想退出 exec 并且只想检查一次 main 中的 return 值。我需要退出哪个进程才能正常工作?

int isValid(void)
{
    int number, statval;
    int child_pid;
    child_pid = fork();
    if(child_pid == -1) { printf("Could not fork! \n"); exit( 1 ); }
    else if(child_pid == 0)
    {
        execl(...); // Child
    }
    else
    {
        // Parent
        waitpid( child_pid, &statval, WUNTRACED );
        if(WIFEXITED(statval))
        {
            if (WEXITSTATUS(statval) == 0)
                return 1;
            else
                return 0;
        }
        else
            printf("Child did not terminate with exit\n");
    }
    return 0;
}

int main(void)
{
    if (isValid())
    {
        printf("Valid\n");
    }
    else
    {
        printf("Invalid\n");
    }
}

您可能应该做一些小事(也许某些 usleep(3) for a few milliseconds) after the fork but before the waitpid to have some real chance to get the waitpid(2) 调用成功。否则,其他进程可能不会被安排到 运行。 顺便说一句,您应该从 waitpid 测试 return 值 ,例如代码

statval = 0;
pid_t wpid = waitpid(child_pid, &statval, WUNTRACED );
if (wpid>0) {
  assert (wpid == child_pid);
  if (WIFEXITED(statval)) {
    if (WEXITSTATUS(statval) == 0)
      return 1;

最后,关于你的问题的标题,阅读job control wikipage, read several chapters of Advanced Linux Programming, and consider using daemon(3)

另外,在execl之后一定要加上

perror("execl");
exit(EXIT_FAILURE);

处理 罕见的 案例 execl 失败。

execl失败时可能出现双倍输出。上面的代码不检查 execl return 值。实际上 execl return 仅在出现故障时出现,因此无需检查 returned 值,但无论如何都需要处理错误。

编辑:

如果 exec 失败则:

  • Child's isValid() returns 函数末尾的 0 和主要打印 "Invalid"
  • Parent 等待 child 退出,然后 WIFEXITED 为真,因为 child 退出,WEXITSTATUS 为 0,因为 child 正常退出。 Parent 的 isValid returns 1 和 "Valid" 被打印出来。
    #include <sys/shm.h>
    int *tabPID;

int isValid(void)
{
    int number, statval;
    if(fork() == 0){
        tabPID[1] = getpid();
        execl(...); // Child
        return -1;
    }
    // Parent
    tabPID[0]=getpid();
    usleep(10);//as Basile Starynkevitch suggests
    waitpid(tabPID[1], &statval, WUNTRACED );
    if(WIFEXITED(statval))
    {
        if (WEXITSTATUS(statval) == 0)
            return 1;
        else
            return 0;
    }
    else
        printf("Child did not terminate with exit\n");
    return 0;
}

int main(void)
{
    shmId = shmget(1234, 2*sizeof(int), IPC_CREAT|0666);
    tabPID = shmat(shmId, NULL, 0);
    if (isValid())
    {
        printf("Valid\n");
    }
    else
    {
        printf("Invalid\n");
    }
}