看看这段代码:
#include<stdio.h>
#include <unistd.h>
int main()
{
int pipefd[2],n;
char buf[100];
if(pipe(pipefd)<0)
printf("Pipe error");
printf("\nRead fd:%d write fd:%d\n",pipefd[0],pipefd[1]);
if(write(pipefd[1],"Hello Dude!\n",12)!=12)
printf("Write error");
if((n=read(pipefd[0],buf,sizeof(buf)))<=0)
printf("Read error");
write(1,buf,n);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望printf在从管道中读取Hello Dude之前打印Read fd并写入fd.但情况并非如此......请看这里.当我在我们的大学计算机实验室尝试相同的程序时,我的输出是
Read fd:3 write fd:4
Hello Dude!
Run Code Online (Sandbox Code Playgroud)
我们的朋友也很少观察到,更改printf语句以包含更多数量的\n字符会改变输出顺序......例如.. printf("\nRead fd:%d\n write fd:%d\n",pipefd[0],pipefd[1]);意味着打印了读取fd然后打印Hello Dude!了写入fd 的消息.这是什么行为?注意:Out lab使用我们运行终端的linux服务器,但我不记得编译器版本.
这是因为printf标准输出流是缓冲的,但是write标准输出文件描述符不是.
这意味着行为可以根据您的缓冲类型而改变.在C中,如果可以确定标准输出连接到交互设备,则标准输出是行缓冲的.否则它是完全缓冲的(请参阅此处以了解为何如此).
行缓冲意味着它会在看到换行符时刷新到文件描述符.完全缓冲意味着它只会在缓冲区填充时刷新(例如,4K值的数据),或者当流关闭时(或当您关闭时fflush).
当您以交互方式运行时,刷新发生在write因为printf遇到\n并自动刷新之前.
然而,当你运行它,否则(如通过重定向输出到文件或在线编译器/执行它可能会做,以捕获演示数据同样的事情),刷新发生后的write(因为printf不是每次冲洗后,每一行).
实际上,根据以下程序,您不需要那里的所有管道内容来查看此操作:
#include <stdio.h>
#include <unistd.h>
int main (void) {
printf ("Hello\n");
write (1, "Goodbye\n", 8);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我执行时myprog ; echo === ; myprog >myprog.out ; cat myprog.out,我得到:
Hello
Goodbye
===
Goodbye
Hello
Run Code Online (Sandbox Code Playgroud)
你可以看到不同类型的缓冲产生的差异.
如果您想要线路缓冲而不管重定向,您可以尝试:
setvbuf (stdin, NULL, _IOLBF, BUFSIZ);
Run Code Online (Sandbox Code Playgroud)
在你的程序的早期 - 它的实现定义了一个实现是否支持这个,所以它可能没有效果,但我没有看到很多它不起作用.