fork - 我可以从父级退出吗?

时间:2016-11-18 11:07:22

标签: c linux fork exec

我已经编写了一个代码,它将调用exec,如下所示。但是,如果我从isValid调用main,则子进程和父进程都将返回,并且我将获得两次输出。

我想从exec中获取并且只想在main中检查返回值一次。我需要退出哪个进程以使其正常工作?

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

3 个答案:

答案 0 :(得分:3)

execl失败时可能会出现加倍输出。上面的代码不会检查execl返回值。实际上execl仅在失败的情况下返回,因此无需检查返回的值,但无论如何都必须处理错误。

修改

如果exec失败,那么:

  • 儿童isValid()在功能结束时返回0,主要打印"无效"
  • Parent等待子退出,然后WIFEXITED为true,因为子退出且WEXITSTATUS为0,因为子进程正常退出。家长isValid返回1和"有效"印刷。

答案 1 :(得分:1)

你可能应该在fork之后但在waitpid之前做一些微小的事情(可能只有usleep(3)几毫秒),以便有机会获得waitpid(2)调用成功。否则,可能会发生其他进程未安排运行的情况。 顺便说一句,你应该从waitpid测试返回值,.e.g。代码

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,阅读Advanced Linux Programming的几个章节,并考虑使用daemon(3)

此外,在execl确定要放

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

处理execl失败的罕见案例。

答案 2 :(得分:1)

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