【问题标题】:Linux Fork: pid reuseLinux Fork:pid重用
【发布时间】:2025-12-16 05:40:01
【问题描述】:

我编写了以下程序来了解在没有 wait() 或 waitpid() 的情况下调用 fork 的工作方式。

int main()
{
    pid_t childpid; 
    int retval = 0; 
    int i; 
    while(1){
        //usleep(1);
        childpid = fork();

        if (childpid >= 0) 
        {
            i++;
            if (childpid == 0) 
            {   
                exit(retval); 
            }
            else 
            {
                //printf("childpid is %d\n", childpid);                     
            }
        }
        else
        {
            printf("total no. of processes created = %d\n", i);
            perror("fork"); 
            exit(0); 
        }
    }
}

这是我得到的输出->

total no. of processes created = 64901
fork: Cannot allocate memory

我希望程序在我立即退出子进程时继续运行,并且 fork() 应该在 pid > pid_max 之后重用 pid。为什么不会发生这种情况?

【问题讨论】:

  • 我很惊讶你没有完全崩溃你的系统。通常有一个用户进程限制来避免这种类型的行为和分叉炸弹。 ulimit -u 应该给你的系统一个非常大的进程限制。这是您系统中的一个主要漏洞。
  • ulimit -u 显示:31488。事实上,该程序甚至可以在后续尝试中运行。

标签: c linux fork


【解决方案1】:

退出的子进程确实作为僵尸保留在进程表中。僵尸进程一直存在,直到它们的父进程调用waitwaitpid 来获取它们的退出状态。并且会保留对应的进程id,防止其他新创建的进程复制。

在您的情况下,进程表变得太大,系统拒绝创建新进程。

分叉进程然后不检索它们的退出状态可以被视为资源泄漏。当父进程退出时,它们会被init进程收养,然后被收割,但是如果父进程存活的时间过长,系统没有办法只删除一些僵尸,因为假设家长应该在某个时候通过waitwaitpid 对它们感兴趣。

【讨论】:

    【解决方案2】:

    子进程也拥有一些资源,比如内存。但是由于父进程无法处理SIGCHLD信号,所以没有释放,子进程退出时会发送。

    那些子进程将变成僵尸。

    您可以使用“ps -aux”来转储这些 fd。

    【讨论】: