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 failed\n");
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
,并在子进程退出时被刷新。
推荐阅读
- r - 如何从 r 将数据发送到 Wordpress 帖子或页面
- python - 如何将函数应用于列表中的连续值对?
- hyperledger-fabric - 一个拥有 5 个对等方的组织的 Hyperledger/fabric 背书策略
- javascript - html中的Javascript调用函数
- magento - Groovy - 序列化 XML NodeChildren
- c++ - 如何在多维数组/网格 C++ 中创建列表
- java - Jboss 和 Hotswap Agent 使用 Jboss 模块
- ruby-on-rails - 针对 Devise 身份验证对多个 Rails 服务器进行身份验证
- c# - 在 LINQ 中按列表分组
- javascript - 将变量公开给 javascript 上下文 (Java / WebView)