C语言 什么争用导致输出看起来不同?



去年的期中考试中,我被问到了这个问题。

请考虑以下程序。

#include <stdio.h>
#include <unistd.h>
int main (void) {
int pid = getpid ();
printf ("hello world (pid:%d)n", pid);
int rc = fork();
if (rc < 0) {
fprintf (stderr, "fork failedn");
retrun 1;
}
pid = getpid();
if (rc == 0) {
printf ("hello, I am child (pid:%d)n", pid);
} else {
printf("hello, I am parent of %d (pid:%d)n", rc, pid);
} 
return 0;
}

并考虑我在编译和运行此程序时遇到的以下行为:

$ gcc -02 -Wall question.c
$ ./a.out # First program run
hello world (pid:20600)
hello, I am parent of 20601 (pid:20600)
hello, I am child (pid:20601)
$ ./a.out | cat # Second program run
hello world (pid:20605)
hello, I am parent of 20607 (pid:20605)
hello world (pid:20605)
hello, I am child (pid:20607)

a( 什么比赛可能导致输出看起来与第一次或第二次运行有很大不同,这个输出会是什么样子?

b( 在两个程序运行的输出中解释每个不同的。

对于(a(部分,我认为子进程和父进程之间存在竞争,子进程可以在父进程之前打印,但显然这是错误的。有没有其他种族会导致输出不同?为什么我的答案是错误的?

对于(b(部分,我在很多事情上都摇摇欲坠。首先,我看到PID在两次运行中都不同,但我对此没有很好的解释。其次,第二次运行中额外的hello world是因为程序使用管道和cat命令运行的方式?

问题是您将输出通过管道传输到cat.

默认情况下,当stdout连接到终端或控制台时,stdout行缓冲的,这意味着内部缓冲区在换行符处刷新(或缓冲区已满或调用fflush时(。

但是,当stdout连接到终端或控制台时,例如当它连接到管道时,它会完全缓冲。这意味着只有在缓冲区已满或调用fflush时才会刷新它。打印换行符不会执行任何特殊操作,换行符只是添加到缓冲区中。

现在,由于stdout已完全缓冲,因此包含第一个printf调用内容的缓冲区将作为fork调用的一部分复制到子进程,并在子进程退出时刷新。

相关内容

最新更新