代码:
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->一次。这是正确的,为什么?(非常感谢我很快就要考试了)
我希望发生这样的事情(检查照片),父级将 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 | 驾驶室 |
printf
。printf
先按“A”,再按“B”,然后退出。printf
是“C”。fork
s。stdout
缓冲区的副本中具有“C”。printf
是一个额外的“A”和“B”,然后退出。printf
一个“C”,则循环终止。printf
是“D”。每个进程在终止时都会刷新其缓冲的输出。各个过程的输出不会混合在一起,但按组分组,它们可以以任何顺序出现。例如,
ABCABCCD
无论如何,总共应该有 2 个 A、2 个 B、3 个 C 和 1 个 D,正如您观察到的那样。