【问题标题】:issues using waitpid() with large number of child process使用带有大量子进程的 waitpid() 的问题
【发布时间】:2021-05-18 16:40:32
【问题描述】:

我有一个 c 程序来创建一个 TCP 套接字并在无限循环中继续等待连接。每次客户端连接到程序时,我都会生成一个新的子进程来处理客户端请求。我的程序只能在信号中断时退出(例如ctrl+c)。

我不希望父进程挂在那里等待一个孩子,我希望他们可以同时工作。 父进程在fork之后应该做的是检查是否有子进程完成,如果是,则清理它们

目前我的做法是(这里没有错误检查以节省空间,我的真实代码中有很多错误检查):

if (fork()==0){
    /* Child process. */
}
else{
    close(client);    /* <- Cut down the connection from parent with the client. */
    waitpid(0, &status_exit, WNOHANG|WUNTRACED);
    child_spawn++;    /* One parent int variable to count total number of child process. */
}

但这引发了另一个问题,因为父进程总是挂起并等待连接,可能总是有一两个先前完成的子进程无法清理,直到父进程可以分叉另一个并清理它们

即使我的程序在退出前收到信号中断后可以清理每个僵尸,但我希望它自己清理每个完成的孩子。

请帮帮我,谢谢。如果我有任何不明白的地方,请发表评论以便我解释。

【问题讨论】:

  • 由于您使用的是WNOHANG,您可以在waitpid 上循环,而它的返回值不是0(不再是死子)而不是-1(错误)。循环 wait 实际上是管理多个进程时使用的正确方法。
  • 这是一个如何等待要么 I/O事件或子进程终止的一般问题的实例,以先到者为准; Unix 从来没有让这变得简单或整洁。我所知道的最简洁的处理方法是使用 Linux 特定的signalfd 接口。一种不太整洁但更便携的方式使用专用于调用waitpid 的线程。还有一个更丑陋的方法,它至少可以避免线程和特定于操作系统的 POSIX 扩展,它是使用pselectSIGCHLD 处理程序。您可以接受这些选项吗?
  • @Jean-BaptisteYunès 谢谢这是个好主意。但是由于父进程会一直等待连接,因此此时完成的任何子进程都将成为僵尸进程,并且在父进程继续之前无法清理。
  • @zwol 我目前正在使用waitpid(0, &amp;status_exit, WNOHANG|WUNTRACED); 在父进程产生子进程以检查是否有任何未清理的已完成进程。
  • @Rrobinvip 你无法避免僵尸......但是,你可以使用SIGCHLD 捕捉死亡并在捕捉函数中循环waitpid

标签: c linux sockets


【解决方案1】:

您可以做的最好的事情是让父母在accept(2) 呼叫的循环中等待,接受客户端的传入连接并派生孩子参加连接。为SIGCHLD 信号注册一个信号处理程序,该处理程序简单地进行wait(2) 调用并将退出代码排队到某个队列中,以便父进程有时间处理。例如,父级可以接受一个连接,派生一个子级并处理中断处理程序排队的所有退出代码以清理子级数据。之后返回accept(2)欢迎新客户。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 1970-01-01
    • 2020-01-15
    • 2020-09-09
    • 2014-05-06
    相关资源
    最近更新 更多