fork()执行过程

6

fork() 函数是如何工作的?

下面这段代码:

#include <stdio.h>

int main (int argc, char const *argv[])
{
printf("Hi\n");
int i;
for(i = 1; i < argc; i++)
{
    printf("Argument %d is %s\n", i, argv[i]);
    fork();
    printf("Forked in for loop increment %d\n", i);
}


return 0;
}

给出以下输出
/a.out hello world 参数1是hello 在for循环增量1中分叉 参数2是world 在for循环增量2中分叉 在for循环增量1中分叉 参数2是world 在for循环增量2中分叉 在for循环增量2中分叉
通常情况下,fork()执行哪些代码?我想了解fork()的原理,而不仅仅是基于这个例子。我可以在命令行上有多个参数。
2个回答

9
fork 是一个系统调用,也就是一个调用内核的库例程。在处理 fork 调用时,内核会创建一个新的进程,该进程执行与调用它的进程相同的程序。新进程开始执行就好像它自己调用了 fork 一样;返回值与父进程不同,因此可以区分这两个进程。
调用 fork 的常见习惯用法是:
pid_t pid = fork();

switch (pid) {
  case -1:
    /* an error occurred, i.e. no child process created */
    handle_error();
  case 0:
    /* a return value of 0 means we're in the child process */
    do_child_stuff();
    break;  // or _exit()
  default:
    /* we're in the parent; pid is the child's process id */
    do_parent_stuff();
}

这是如何工作的:操作系统创建一个接近完美的进程副本,调用 fork 的进程(PID和一些其他值不同,但内存内容基本相同并且通常两个进程都打开相同的文件)。 拷贝通常使用所谓的写时复制(COW)语义完成,因此直到其中一个进程开始分配变量,几乎没有实际拷贝。

所以我的打印输出结果是误导我的。在for循环中使用fork()很奇怪,对吧? - some_id
2
你的程序的输出顺序是不确定的。在循环中使用 fork 不太奇怪(您可能想要创建一些 n 个工作进程),但是裸 fork(即子进程和父进程运行相同代码)非常罕见。大多数情况下,fork 只是为调用 exec 做准备。 - Fred Foo
1
@Helium3 有点奇怪的是,代码没有将fork的返回值存储在一个名为childpid的变量中,然后根据它是0(在子进程中)、正数(在父进程中)还是负数(失败)来执行不同的操作。这可能发生在循环中或不在循环中。 - Jim Balter
一个人怎样使用这些 pid?在上述的 switch 中,人们是否会知道哪个 pid 会执行,因为 pid_t pid = fork(); 返回一个具体的 pid,或者为什么返回的 pid 可能是子进程或者父进程?一个人如何随后根据需要使用这些 pid?是否有可能在一个 pid 上使用一些库函数,比如(猜测一下)sleep() 或 kill()。fork 出的进程能否递归地创建所需数量的进程,并从主进程中跟踪它们? - some_id
当然可以。我只是想知道,如果pid被设置为进程创建的失败或成功,是什么阻止它在switch中执行-1或0? - some_id
显示剩余3条评论

3
请注意进程数量呈指数增长,因此对于100个参数,我们将谈论1267650600228229401496703205376个进程。希望您有一台真正强大的电脑:)。
我将在此回答您的评论,这可能有助于您了解fork。
每次循环后,您将使进程数量翻倍。因此,在N个循环后,您将得到2^N个进程。或者在100个循环后,您将得到我给您的那个巨大的数字。
顺便说一句,fork bombs是最常见的DoS攻击之一:)。

这有点夸张了。 ;) 你是怎么得出那个数字的? - some_id
每个参数都会使派生进程的数量翻倍。因此,最终你将拥有2^n个进程。很长一段时间内,大多数操作系统一次无法管理超过2^16个进程,这是由于进程ID(PID)以前通常是一个16位数字。即使今天的操作系统大多使用32位类型的PID,通常也会有一个2^16的限制。但是,在一个系统上很少会同时产生超过1000个进程。 - datenwolf
谢谢你提供的信息。@Klark:分叉炸弹链接很有趣,谢谢。 - some_id

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接