在 C 中等待子进程终止的最佳实践
Posted
技术标签:
【中文标题】在 C 中等待子进程终止的最佳实践【英文标题】:Best practice for waiting for a child process termination in C 【发布时间】:2021-12-14 06:15:47 【问题描述】:我正在编写一个 C 库,它会在某个时候分叉另一个进程,然后等待其完成。
我想以最稳健和通用的方式编写等待子进程完成的代码,以处理所有可能的情况,例如调用进程产生其他子进程、接收信号等。
以下 C 代码是否正确使用waitpid
,即以最稳健的方式?
void waitForChildProcess(int child_pid)
int rc, err;
do
//waiting only for my own child and only for its termination.
//The status value is irrelevant (I think) because option '0' should mean
//to only wait for a child termination event
// and I don't care about the child's exit code:
rc = waitpid(child_pid, NULL, 0);
err = errno;
while (rc == -1 && err == EINTR); //ignoring a signal
【问题讨论】:
如果你在生成子进程后什么都不做,fork()
不是更容易吗?
@Matthieu fork()
是产生子进程的函数。父进程获取子进程 PID 的副本,OP 希望使用该信息等待子进程终止。
【参考方案1】:
是的,waitpid(child_pid, ...) 是最稳健的方式。
如果子进程已经退出,它将返回 child_pid,如果发生错误,则返回 -1 并设置errno
(ECHILD
如果子进程不存在(从未创建或已被收割)或不是此进程的子进程,EINVAL
如果选项(第三个参数)具有无效值,或者 EINTR
如果信号被传递到未安装 SA_RESTART 标志的信号处理程序),或者0
如果WNOHANG
选项(第三个参数)已指定,子进程尚未退出。
不过,我建议稍作改动:
/* Wait for child process to exit.
* @child_pid Process ID of the child process
* @status Pointer to where the child status
* is stored; may be NULL
* @return 0 if success
* -1 if an error occurs, see errno.
*/
int waitForChildProcess(pid_t child_pid, int *status)
int rc;
if (child_pid <= 1)
errno = EINVAL;
return -1;
do
rc = waipid(child_pid, status, 0);
while (rc == -1 && errno == EINTR);
if (rc == child_pid)
return 0;
/* This should not happen, but let's be careful. */
if (rc != -1)
errno = ECHILD;
return -1;
在 Linux 和 POSIXy 系统中,进程 ID 是正整数。正如您在man 2 waitpid 手册页中所见,零和负PID 指的是进程组,而-1 指的是任何子进程。进程1特殊,init
;它永远不会退出并设置其余的用户空间。因此,当前进程的子进程可以拥有的最小 PID 是 2。
我认为为这些使用正确的类型是明智的:pid_t
用于进程 ID,例如 size_t
用于对象的内存大小(包括 strlen()
的返回值。)
提供status
指针(以便调用者可以使用WIFEXITED()
+WEXITSTATUS()
或WIFSIGNALED()
+WTERMSIG()
进行检查)很方便,因为任何对它不感兴趣的调用者都可以提供@987654339 @。 (NULL
明确允许用于 wait()
和 waitpid()
的状态指针。)
从技术上讲,options==0
、waitpid()
应该只返回子 PID 或 -1(设置 errno
)。但是,由于检查非常便宜,我更愿意将其他所有内容都视为 ECHILD 错误,因为这样会得到最可靠的结果。
调用者可以随意忽略返回值。但是,如果他们想知道,如果成功则返回值为 0,否则为 -1 并设置 errno
(并且 strerror(errno)
提供了文本原因)。
【讨论】:
我没有'-1;你的答案,但我看不出额外的代码行如何带来更多的健壮性。例如,在 while 循环之后,'rc' 怎么可能是 child_pid 或 -1 以外的任何值?以上是关于在 C 中等待子进程终止的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章