STDOUT缓冲区在哪里?

时间:2013-02-18 10:00:59

标签: c linux

众所周知,STDOUT在Linux中是缓冲的。我的问题是:1)它是一个由所有进程共享的全局缓冲区吗?或每个过程一个缓冲区? 2)缓冲区在哪里?在堆栈,或堆或静态区域? 3)谁创造了它?

3 个答案:

答案 0 :(得分:3)

stdout是由标准库创建的C FILE指针,因此相关代码将作为C库的一部分加载。在Linux上,它将以Posix文件描述符的形式实现。

你的C库和内核都可以使用缓冲;你必须检查个别文件。我建议首先查看C库源代码的相关部分(即实现<stdio.h>的部分),这应该是非常有教育意义的。

答案 1 :(得分:2)

最令人难以理解的关于C标准库的最佳资源是P. J. Plauger的The Standard C Library。他描述了他自己实施图书馆时出现的所有问题(在MSWord!在win3.1笔记本电脑上!度假!)。

他还提供了有关如何使用(和测试)每个功能的详细信息。

对于Unix(Linux)方面,您应该开始阅读'inode',这是用于存储内存缓存文件的经典数据结构。经典着作是Maurice J. Bach的The Design of the UNIX Operating System


好了,既然你因为没有阅读所有旧书和每个相关的维基页而受到适当的责骂。

以下是标准C库的相关引用,p。 256。

  

原则上,您可以对I / O函数如何缓冲流的数据进行一定程度的控制。但是,您必须意识到,缓冲是基于有关I / O模式的各种猜想的优化。这些猜想通常是正确的,许多实现都遵循您的建议。但他们没有必要。实现可以忽略大多数缓冲请求。

     

然而,如果你认为更大的缓冲区会提高性能,或者更小的缓冲区会节省空间,你可以提供自己的候选缓冲区。打开文件后,在对流执行任何其他操作之前,请调用函数setvbuf。 (避免使用较不灵活的旧函数setbuf。)您可以指定I / O是应该完全缓冲,是通过文本行缓冲还是无缓冲。它可能会对您的计划执行情况产生影响。

     

...

     

setbuf - 使用setvbuf代替此功能来获得更多控制权。

     

setvbuf - 通常,最好让标准C库决定如何缓冲输入/输出。如果您确定不需要缓冲或一次一行缓冲,请使用此函数正确初始化流。打开流后,立即致电setvbuf 。几乎所有关于流的操作都将优先于您选择缓冲策略的权利。如果您使用此调用指定自己的缓冲区,请不要假设流实际上将使用它。并且从不在流打开时改变缓冲区的内容。 模式(第三个)参数必须具有上述值_IOFBF_IOLBF_IONBF之一。另请参阅宏[{1}},描述[其他地方]。

     

...

BUFSIZ

因此,至少在此实现中,默认缓冲区可能存在于FILE结构中并在堆上分配。我们可以在这里看到它的兄弟,一个字符缓冲区(/* setbuf function */ #include "xstdio.h" int (setbuf)(FILE *str, char *buf) { /* set up buffer for a stream */ setvbuf(str, buf, buf ? _IOFBF : _IONBF, BUFSIZ); } /* setvbuf function */ #include <limits.h> #include <stdlib.h> #include "xstdio.h" int (setvbuf)(FILE *str, char *abuf, int smode, size_t size) { /* set up buffer for a stream */ int mode; unsigned char *buf = (unsigned char *)abuf; if (str->_Mode & (_MREAD|_MWRITE)) return (-1); mode = smode == _IOFBF ? 0 : smode == _IOLBF ? _MLBF : smode == _IONBF ? _MNBF : -1; if (mode == -1) return (-1); if (size == 0) buf = &str->_Cbuf, size = 1; else if (INT_MAX < size) size = INT_MAX; if (buf) ; else if ((buf = malloc(size)) == NULL) return (-1); else mode |= _MALBUF; if (str->_Mode & _MALBUF) free(str->_Buf), str->_Mode &= ~_MALBUF; str->_Mode |= mode; str->_Buf = buf; str->_Bend = buf + size; str->_Next = buf; str->_Rend = buf; str->_Wend = buf; return (0); } ),用于“无缓冲”。

答案 2 :(得分:0)

这取决于你如何写入stdout。如果你使用stdio,如果输出变为tty,它将被行缓冲。否则它将被完全缓冲。

有关详细信息,另请参阅man stdio

如果使用write之类的低级例程,则只写入给定的字节。根据目标,内核中将有缓冲。如果目标是tty,则可以直接写入终端。