c - 为什么在我的centos中打印三次 'hello'?

标签 c fork

#include "csapp.h"

int main()
{
        int i;

        for (i = 0; i < 2; i++)
                fork();
        printf("hello\n");
        exit(0);
}
/*
 *                .------------------------
 *                |
 *                |
 *                |
 *    .-----------.------------------------
 *    |
 *    |
 *    |           .------------------------
 *    |           |
 *    |           |
 *    |           |
 *    .-----------.------------------------
 *   fork        fork
 *   i=0         i=1
 */

在流程图片中,代码似乎会打印四次“hello”。 为什么在我的 centos 中打印 3 次 'hello'?

最佳答案

除非您的 csapp.h header 中有什么奇怪的东西,否则您应该打印出四行,因为在循环的第一次迭代之后(i == 0 之前增量),fork() 创建两个进程,并且在第二次迭代(增量之前的 i == 1),这两个进程中的每一个都执行 fork() 以创建另外两个进程。

当这段代码在 macOS 10.14.6 上运行时,我得到 4 行 hello:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
        int i;

        for (i = 0; i < 2; i++)
                fork();
        printf("hello\n");
        exit(0);
}

输出:

hello
hello
hello
hello

不过,我对它的检测远不止问题中显示的最少代码 — 像这样:

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    int i;
    printf("P0: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
    fflush(stdout);

    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        printf("PF: i = %d, PID = %d, PPID = %d, fork = %d\n",
                i, (int)getpid(), (int)getppid(), pid);
        fflush(stdout);
    }
    printf("Hello: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
    return(0);
}

注意大量使用 fflush() 以避免 printf() anomaly after fork() .

我从中得到的示例输出是:

P0: PID = 5039, PPID = 916
PF: i = 0, PID = 5039, PPID = 916, fork = 5042
PF: i = 1, PID = 5039, PPID = 916, fork = 5043
Hello: PID = 5039, PPID = 916
PF: i = 0, PID = 5042, PPID = 5039, fork = 0
PF: i = 1, PID = 5043, PPID = 1, fork = 0
Hello: PID = 5043, PPID = 1
PF: i = 1, PID = 5042, PPID = 1, fork = 5044
Hello: PID = 5042, PPID = 1
PF: i = 1, PID = 5044, PPID = 5042, fork = 0
Hello: PID = 5044, PPID = 5042

请注意,其中两个进程报告 PPID = 1,因为父进程 (5039) 已经退出。添加一个循环来等待 child 死亡并报告他们的退出状态是可行/明智的。

#include <sys/wait.h>

…

int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
    printf("WT: PID = %d, PPID = %d, child %d exited 0x%.4X\n",
           (int)getpid(), (int)getppid(), corpse, status);
    fflush(stdout);
}

你在 CentOS 上得到了什么?

我在终端窗口中从命令行运行程序。如果您从 IDE 或其他东西运行它,您可能会丢失孤立进程的输出。添加 wait() 循环将阻止第一个进程退出,直到它的所有(两个)子进程都退出,从而导致有序显示 4 个“Hello”行。我重新设计了输出格式,以便更容易阅读输出。

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void)
{
    int i;
    printf("P0: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
    fflush(stdout);

    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        printf("PF: PID = %5d, PPID = %5d, i = %d, fork = %5d\n",
                (int)getpid(), (int)getppid(), i, pid);
        fflush(stdout);
    }

    printf("hello\n");
    printf("HO: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
    fflush(stdout);

    int corpse;
    int status;
    while ((corpse = wait(&status)) > 0)
    {
        printf("WT: PID = %5d, PPID = %5d, child %5d exited 0x%.4X\n",
                (int)getpid(), (int)getppid(), corpse, status);
        fflush(stdout);
    }

    printf("EX: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
    return(0);
}

示例输出(无孤立进程):

P0: PID =  5245, PPID =   916
PF: PID =  5245, PPID =   916, i = 0, fork =  5248
PF: PID =  5248, PPID =  5245, i = 0, fork =     0
PF: PID =  5245, PPID =   916, i = 1, fork =  5249
hello
HO: PID =  5245, PPID =   916
PF: PID =  5248, PPID =  5245, i = 1, fork =  5250
PF: PID =  5249, PPID =  5245, i = 1, fork =     0
hello
HO: PID =  5248, PPID =  5245
hello
HO: PID =  5249, PPID =  5245
EX: PID =  5249, PPID =  5245
PF: PID =  5250, PPID =  5248, i = 1, fork =     0
hello
HO: PID =  5250, PPID =  5248
EX: PID =  5250, PPID =  5248
WT: PID =  5245, PPID =   916, child  5249 exited 0x0000
WT: PID =  5248, PPID =  5245, child  5250 exited 0x0000
EX: PID =  5248, PPID =  5245
WT: PID =  5245, PPID =   916, child  5248 exited 0x0000
EX: PID =  5245, PPID =   916

关于c - 为什么在我的centos中打印三次 'hello'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57199284/

相关文章:

c - c 中的 pipe() 和 fork()

c - 每个父进程不允许在其子进程之前终止

c - 将结构体指针作为参数传递给 C 中的函数

c - 释放仅在 MEX 文件中使用的数组是否会带来加速

c - 为什么我得到 "floating point exception (core dumped)"?

C linux共享内存不能存储大整数值

c++ - 缩放后重新定位矩形

c - 使用 fork : accessing child process memory from parent

process - 如何向通过 fork 和 execl 创建的子进程发送信号?

c - 标准流和 vfork