【发布时间】:2019-12-05 07:11:22
【问题描述】:
我在去年的期中考试中被问到这个问题。
考虑以下程序。
#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 命令运行的方式?
【问题讨论】:
-
请记住,
fork创建了父进程的完全相同的副本,包括stdout使用的缓冲区(这是printf写入的位置)。在第二种情况下,似乎第一个printf调用的缓冲区在进程分叉时没有被刷新。 -
@Someprogrammerdude,我很好奇:stdout 不应该被第一个
printf处的\ncharacter 刷新? -
@GuillaumePetitjean 谢谢,这为我指明了正确的方向! :)
-
作为旁注,考虑到英语很差,我希望它们不是真正的考试题...
-
@GuillaumePetitjean 是 :) 操作系统课程
标签: c pipe fork child-process