如果 execvp() 失败,每个数字会打印多少次?我跑步时得到 C 3 次,但我的逻辑说 C 2 次

问题描述 投票:0回答:1

代码:

int main(int argc, char *argv[]) {
    int i;
    for (i = 1; i < 3; i++) {
        if (fork() == 0) {
            printf("A");
            execvp("./prog2", &argv[1]);
            printf("B");
            exit(1);
        } 

        printf("C");
    }

    printf("D");
    return 0;
}

我希望发生这样的事情(检查照片),父级将 C 保存到其缓冲区中(第一次迭代),然后在第二次迭代后保存 CC,最后打印 CCD,至于子级,首先打印 AB,然后在第二次迭代时退出相同(第二次迭代)。所以我会说:A->两次,B->两次,C->两次,D->一次。但我运行时得到的是:A->两次,B->两次,C->三次,D->一次。这是正确的,为什么?(非常感谢我很快就要考试了)photo

c for-loop printf buffer fork
1个回答
0
投票

我希望发生这样的事情(检查照片),父级将 C 保存到其缓冲区中(第一次迭代),然后在第二次迭代后保存 CC,最后打印 CCD,至于子级,首先打印 AB,然后在第二次迭代时退出相同(第二次迭代)。所以我会说:A->两次,B->两次,C->两次,D->一次。但我运行时得到的是:A->两次,B->两次,C->三次,D->一次。哪个是正确的,为什么?

标准输出默认被缓冲,并且缓冲区位于进程的内存中。因此,每次父进程分叉时,子进程都会收到父进程的 stdout 缓冲区的副本,包括当时保存的任何内容。

在第一个 fork 时,父级的缓冲区为空,但在第二个 fork 时,它包含父级在第一次循环迭代结束时打印的“C”。父母和(第二个)孩子最终都会打印出“C”,这说明了您观察到的超出预期的部分。您可以通过在循环底部插入对

fflush(stdout)
的调用来避免这种情况。

假设所有

fork()
printf()
exit()
调用均成功,并且所有
execvp()
均失败,则各个进程中输出缓冲区内容的演变如下:

  P1 P2 P3
1, 2      
3   AB
4,5 C AB
6 C AB C
7 C AB 驾驶室
8 抄送 AB 驾驶室
9 CCD AB 驾驶室
  1. P1 作为唯一进程进入循环,尚未调用
    printf
  2. P1 然后分叉 P2,并且在循环的迭代中,
  3. P2
    printf
    先按“A”,再按“B”,然后退出。
  4. P1
    printf
    是“C”。
  5. P1 然后循环回到循环顶部并再次
    fork
    s。
  6. P3 是从 P1 分叉出来的,最初在其
    stdout
    缓冲区的副本中具有“C”。
  7. P3
    printf
    是一个额外的“A”和“B”,然后退出。
  8. P1
    printf
    一个“C”,则循环终止。
  9. 最后,P1
    printf
    是“D”。

每个进程在终止时都会刷新其缓冲的输出。各个过程的输出不会混合在一起,但按组分组,它们可以以任何顺序出现。例如,

ABCABCCD

无论如何,总共应该有 2 个 A、2 个 B、3 个 C 和 1 个 D,正如您观察到的那样。

© www.soinside.com 2019 - 2024. All rights reserved.