4

考虑下面的代码片段:

int main()
{
    fork();
    fork();
    fork();
    printf("Hello World\n");
}

我得到了输出:[ubuntu 12.04]

aashish@aashish-laptop:~$ ./a.out
Hello World
Hello World
Hello World
aashish@aashish-laptop:~$ Hello World <---------------------------
Hello World
Hello World
Hello World
Hello World

为什么流程执行结束后会输出“Hello Word”?

4

4 回答 4

5

简短的回答是您正在创建多个进程,这些进程彼此异步运行。长答案如下:

当您在 shell 提示符下键入./a.out时,会创建一个运行您的程序的进程。我们称这个过程为 1。

进程 1 调用 fork()。这将创建一个新的子进程,进程 2,并且 1 和 2 在第一次 fork() 调用之后继续执行,继续进行第二次 fork() 调用。进程 1 创建子进程 3,进程 2 创建子进程 4。所有四个进程都在第二个 fork() 之后继续,继续到最后的 fork() 调用。流程 1 创建流程 5;流程 2 创建流程 6;流程 3 创建流程 7;过程 4 创建过程 8。

非艺术家对流程层次结构的渲染

请注意,这些进程编号是任意的:不能保证它们会按该顺序创建。

一旦第一个 fork() 被执行,异步就开始发挥作用。系统不提供关于调度父级与子级的保证。理论上,孩子可以在父母继续之前完成,父母可以在孩子获得任何资源之前完成。最可能的情况是在中间的某个地方:原始进程与其子进程共享资源,因此所有进程都同时运行。

谜题的最后一部分源于 shell 正在等待进程 1 完成这一事实。只有进程 1。shell 不知道(或关心)进程 1 已启动其他进程。所以当 Process 1 完成时,shell 会显示一个提示。碰巧的是,进程 1 的一些后代还没有到达 printf() 语句。当他们到达那里时,shell 已经显示了它的提示符。

要进一步探索这一点,您可能想尝试将fork()调用更改为printf("%d\n", fork()); 和/或将printf("Hello World\n")更改为printf("Hello from pid %d\n", getpid() )

于 2012-08-03T21:39:40.903 回答
3

在第二个 shell 提示符之后出现的“Hello World”输出来自分叉的进程,而不是来自 shell(你)启动的那个。

于 2012-08-03T19:29:17.773 回答
0

那是因为你做了 1 个分叉 (2),然后你再分叉 (4),然后再分叉 (8),然后为每个分叉打印 Hello world。这就是为什么你有 8 个输出。

于 2012-08-03T19:31:21.950 回答
0
int main() {
    pid_t c[3];
    int i, n = 0;
    for (i = 0; i < 3; ++i) {
        switch ((c[n] = fork())) {
        case 0:  break;
        case -1: perror("fork"); exit(EXIT_FAILURE);
        default: ++n;
        }
    }
    printf("[%d] Hello World\n", (int)getpid());
    // Without waiting, some children may still be running when the
    // parent exits. This makes it look like output is generated
    // after the process is over, when in fact not all the processes
    // are done yet.
    //
    // The process is not really finished until its children are
    // finished. The wait call waits on a child process to finish.
    for (i = 0; i < n; ++i) wait(0);
    return 0;
}
于 2012-08-03T19:43:04.180 回答