“声明”在这种情况下是错误的; C 用这个词来谈论仅仅断言某物存在的结构,例如
extern int fork(void);
是函数fork的声明。在您的代码中写入(或因#include <unistd.h> 而为您编写)不会导致调用fork。
现在,您的示例代码中的语句 child = fork(); 当写在函数体中时,会(生成代码以)调用函数fork。该函数,假设它实际上是您操作系统上的系统原语fork(2),并假设它成功,具有返回两次的特殊行为,一次在原始进程中,一次在新进程中,每个都有不同的返回值,所以你可以知道哪个是哪个。
因此,您的问题的答案是,在您展示的两个代码片段中,假设我在上一段中提到的内容,child = fork(); 行之后的所有代码至少可能执行两次,一次由孩子和父母一次。 if (child == 0) { ... } 构造(同样,这不是“声明”)是让父母和孩子做不同事情的标准习语。
编辑:在您的第三个代码示例中,是的,child1 == 0 块是必需的,但不能确保创建子项。相反,它可以确保您希望 child1 执行的任何操作do 仅在 child1 中完成。此外,正如所写(并且再次假设所有调用都成功),您正在创建 三个 子进程,因为 second 分叉调用将由父子进程执行!你可能想要这样的东西:
pid_t child1, child2;
int status;
child1 = fork();
if (child1 == -1) {
perror("fork");
exit(1);
}
else if (child1 == 0) {
execlp("program_to_run_in_child_1", (char *)0);
/* if we get here, exec failed */
_exit(127);
}
child2 = fork();
if (child2 == -1) {
perror("fork");
kill(child1, SIGTERM);
exit(1);
}
else if (child2 == 0) {
execlp("program_to_run_in_child_2", (char *)0);
/* if we get here, exec failed */
_exit(127);
}
/* control reaches this point only in the parent and only when
both fork calls succeeded */
if (waitpid(child1, &status, 0) != child1) {
perror("waitpid");
kill(child1, SIGTERM);
}
/* only use SIGKILL as a last resort */
kill(child2, SIGTERM);
仅供参考,这只是一个骨架。如果我正在编写代码来真正做到这一点(我有:例如参见https://github.com/zackw/tbbscraper/blob/master/scripts/isolate.c),那么将有更多的代码来全面检测和报告错误,以及处理文件描述符管理所需的额外逻辑孩子们和其他一些皱纹。