如何正确退出子进程?

时间:2019-02-22 11:22:35

标签: c fork

通过以下代码示例,我希望我的子进程将正常退出:

int main(void)
{
    for (int i = 0; i < 100; ++i)
    {
        int pid = fork();
        printf("pid %d\n", pid);
        sleep(1);
        if (pid == 0)
            exit(0);
    }
}

但是当我运行ps时,会得到以下输出:

5089 pts/0    00:00:00 test
5090 pts/0    00:00:00 test <defunct>
5091 pts/0    00:00:00 test <defunct>
5092 pts/0    00:00:00 test <defunct>
5094 pts/0    00:00:00 test <defunct>

如何使子进程正常退出?

3 个答案:

答案 0 :(得分:4)

父进程必须调用wait函数之一(wait,waitpid,waitid,wait4),以释放子进程资源。请参见waitpid的联机帮助页:

WAIT(2)

NAME
       wait, waitpid, waitid - wait for process to change state

SYNOPSIS
       #include <sys/types.h>
       #include <sys/wait.h>

       pid_t wait(int *wstatus);

       pid_t waitpid(pid_t pid, int *wstatus, int options);

       int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
                       /* This is the glibc and POSIX interface; see
                          NOTES for information on the raw system call. */

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       waitid():
           Since glibc 2.26: _XOPEN_SOURCE >= 500 ||
               _POSIX_C_SOURCE >= 200809L
           Glibc 2.25 and earlier:
               _XOPEN_SOURCE
                   || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
                   || /* Glibc versions <= 2.19: */ _BSD_SOURCE

DESCRIPTION

…

       In the case of a terminated child, performing a wait
       allows the system to release the resources associated with the child;
       if a wait is not performed, then the terminated child remains in a
       "zombie" state (see NOTES below).

答案 1 :(得分:1)

如果wait未被父级调用,然后子级终止-那么它(子级)仍然是僵尸-无限期地等待其退出状态的获得。这就是您的情况。

如果您不想在父母中打电话给wait,那么您必须将孩子创建为独立的流程。 daemon() 可能 可以为您提供帮助。 http://man7.org/linux/man-pages/man3/daemon.3.html

答案 2 :(得分:1)

您的进程已正常退出。 <defunct>表示该进程已死,唯一剩下的就是其PID和退出状态。

要清除进程表中的这些<defunct>条目,父进程必须为其子进程使用wait()或退出自身。在后一种情况下(父进程死亡),子进程变为孤立进程,并被init(具有PID 1的进程)采用,然后对其进行清理。

在某些系统上, 1 您也可以忽略SIGCHLD信号:

signal(SIGCHLD, SIG_IGN);

这意味着子进程将立即获得。


1 POSIX lists this feature作为XSI扩展。尽管不是POSIX一致性所必需的,但所有XSI conforming系统都将支持它。