下面代码的目标是创建 4 个子进程而不生成任何孙进程。如果 fork 函数按预期运行,则代码可以正确运行。如果在创建第一个子进程时 fork 失败,代码将适当地处理失败。
但是,我很好奇创建了3个子进程,然后创建第四个子进程时fork失败的情况。在这种情况下,如果我的理解是正确的,父进程将退出,但 3 个已创建的子进程仍将运行。
如果是这样,如何在父进程退出之前杀死所有创建的子进程?
编辑:我愿意接受任何改进代码的建议。
void create_subprocessies(int pids[], int pid_parent)
{
for (int i = 0; i < 4; i++)
{
if (pid_parent != getppid())
{
if ((pids[i] = fork()) == -1)
{
perror("Fork");
exit(-1);
}
}
}
}
void create_subprocesses(size_t npids, int pids[npids])
{
for (size_t i = 0; i < npids; i++)
{
if ((pids[i] = fork()) == -1)
{
perror("fork() failed");
for (size_t j = 0; j < i; j++)
kill(pids[j], SIGTERM);
exit(-1);
}
else if (pids[i] == 0)
{
be_childish(…);
exit(-1);
}
}
}
注意修改后的界面,它修复了拼写错误并指示应启动多少个进程。
be_childish()
函数执行子进程应该执行的任何操作。 如果它是一个 _Noreturn
函数(如果它具有属性 [[noreturn]]
或 C23 中的等效属性),那么它后面的 exit()
不是必需的,但它确保子级不会继续,因此这是一种防御形式编程。 如果子项的论点不容易确定,那么您可能存在设计问题。 然后您可能需要安排孩子们回来,但这可能不是一个舒适的设计。
您可以安排
create_subprocesses()
函数接受函数指针和参数:
void create_subprocesses(size_t npids, int pids[npids], void (*child)(void *data), void *data)
{
…
else if (pids[i] == 0)
{
(*child)(data); // Or: child(data);
exit(-1);
}
…
}
这假设孩子们都获得相同的数据。 如果需要,您可以通过传递包含函数指针和参数的结构体数组来为每个子级安排不同的函数和不同的数据。
如图所示,该函数仅在所有子进程成功 fork 后才在父进程中返回。
SIGTERM
信号向子进程表明它应该终止。 您可以使用 SIGHUP
代替,尽管它的含义略有不同。 您通常不应使用 SIGKILL
或其他信号。