Squ*_*dly 8 c linux bash fork pipe
我在fork上看了一些简单的代码,并决定自己尝试一下.我编译然后从Emacs内部运行它,并获得一个不同的输出到通过在Bash中运行它产生的输出.
#include <unistd.h>
#include <stdio.h>
int main() {
if (fork() != 0) {
printf("%d: X\n", getpid());
}
if (fork() != 0) {
printf("%d: Y\n", getpid());
}
printf("%d: Z\n", getpid());
}
Run Code Online (Sandbox Code Playgroud)
我用gcc编译它,然后从Emacs内部运行a.out cat,并将它管道输送到grep .,然后得到它.
2055:X
2055:Y
2055:Z
2055:X
2058:Z
2057:Y
2057:Z
2059:Z
这不对.只是从Bash运行它我得到(我预期)
2084:X
2084:Y
2084:Z
2085:Y
2085:Z
2087:Z
2086:Z
编辑 - 错过了一些换行符
这是怎么回事?
asc*_*ler 11
不同进程写入其输出的顺序完全不可预测.所以唯一令人惊讶的是,有时"X"打印语句有时会发生两次.
我相信这是因为有时在第二个fork(),包含"X"的输出行在输出缓冲区中,需要刷新.所以这两个过程最终打印出来.由于getpid()已经调用并转换为字符串,因此它们将显示相同的pid.
我能够重现多条"X"线,但如果我fflush(stdout);在第二条线之前添加fork(),我总是只能看到一条"X"线,总共只有7条线.
我想我知道发生了什么事.当输出是tty而不是管道或文件时,stdio缓冲将是不同的.子进程继承父缓冲区.当他们被冲洗时,你可以获得双倍输出.
如果你添加
fflush(stdout);
Run Code Online (Sandbox Code Playgroud)
每次printf()通话结束后,你会明白我的意思.
有趣的是,当标准输出是tty设备时,它会有所不同.可能是库知道这意味着什么,并在每次换行后刷新,或类似的东西.
所以我想你会想知道为什么你会得到一个以上的"X"?
这是因为缓冲输出被刷新两次.
当您管道程序的输出时,stdio库会识别出您的输出不是终端,并且它会切换到块缓冲而不是行缓冲.因此,当进程分叉时,现在父进程和子进程都有待处理输出时,还没有任何输出.
| 归档时间: |
|
| 查看次数: |
254 次 |
| 最近记录: |