C标准I/O与UNIX I/O基础知识比较

16

我有一个非常基础的问题。在我的教授的讲义幻灯片中,有一个示例我不太理解。

她写道:

printf("u"); 
write(STDOUT_FILENO, "m", 1); 
printf("d\n");

...她说这段代码的输出结果会是:

mud

我不懂,如果有人知道为什么会这样,请解释一下。

参考这个问题:

http://lagoon.cs.umd.edu/216/Lectures/lect17.pdf
(在倒数第二张幻灯片页面。)
2个回答

24

write 是一个系统调用 -- 它由用户模式(您的程序运行的地方)和操作系统内核(在将字节写入文件时处理实际写入磁盘的地方)之间的接口实现。

printf 是 C 标准库函数 -- 它由加载到用户模式程序中的库代码实现。

C 标准库输出函数默认缓存其输出,直到达到行末标志。当缓冲区已满或以换行符结尾时,通过库实现调用 write 将其写入文件。

因此,通过 printf 输出的内容不会立即发送到操作系统的 write。在您的示例中,您缓冲字母 'u',然后立即写入字母 'm',然后将 "d\n" 追加到缓冲区,标准库通过调用 write(STDOUT_FILENO, "ud\n"); 来将其写入。


10

默认情况下,stdout行缓冲的(line-buffered);它只有在遇到换行符(或者缓冲区填满)时才会刷新输出。

因此,"u" 会一直停留在缓冲区中,直到接收到 "d\n"。但是 write 可以绕过这个缓冲区。


我不会说写入操作“颠覆”了什么。缓冲区完好无损且正常工作。更准确地说,写入操作是一个系统调用,而printf是一个库函数。 - Heath Hunnicutt
2
stdout 默认情况下不是行缓冲的。 如果 stdout 关联到 tty,则默认情况下它是行缓冲的。 如果 stdout 是常规文件或管道(或真正除了 tty 之外的任何东西),则默认情况下它将被块缓冲。 - William Pursell
@WilliamPursell:从技术上讲,如果可以确定stdout不是交互式设备,则它可能是块缓冲而不是行缓冲。 - ninjalj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接