STDOUT缓冲区在哪里?

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

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

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

PJ Plauger的标准C语言库是学习C标准库的最佳资源。 他描述了自己实施图书馆时出现的所有问题(在一台win3.1笔记本电脑上的MSWord!上!)。

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

对于Unix(Linux)方面,您应该开始阅读“inode”,这是用于存储内存缓存文件的经典数据结构。 这本书的经典之作是Maurice J. Bach 的“UNIX操作系统的设计”


好吧,既然你没有阅读所有的旧书和所有相关的wiki页面,现在你已经被适当的谴责了。

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

原则上,您可以对I / O功能缓冲数据流的方式进行一定程度的控制。 但是,您必须认识到,缓冲是基于对I / O模式的各种猜测的优化。 这些猜测通常是正确的,许多实现遵循你的建议。 但他们不需要。 一个实现可以自由地忽略大部分的缓冲请求。

不过,如果您认为更大的缓冲区可以提高性能,或者更小的缓冲区可以节省空间,则可以提供您自己的候选缓冲区。 在打开文件之后,在流上执行任何其他操作之前,请调用函数setvbuf 。 (避免旧的函数setbuf ,这是不灵活的。)您可以指定I / O是否应该完全缓冲,文本行缓冲或无缓冲。 这可能会影响程序执行的效果。

setbuf – 使用setvbuf代替这个函数来获得更多的控制。

setvbuf – 通常,最好让标准C库决定如何为您缓冲输入/输出。 如果您确定不需要缓冲或一次一行缓冲,则可以使用此函数正确初始化流。 打开流后立即调用setvbuf 。 几乎在流上的任何操作都将阻止您选择缓冲策略的权利。 如果您使用此调用指定您自己的缓冲区,请不要假定该流将实际使用它。 在流打开的时候不要改变缓冲区的内容。 模式 (第三个)参数必须具有上述值_IOFBF_IOLBF_IONBF中的一个。 另请参阅[其他]中描述的宏BUFSIZ

 /* 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); } 

所以,至少在这个实现中,默认的缓冲区可能存在于FILE结构中,并被分配到堆上。 我们可以在这里看到它的兄弟,一个字符缓冲区( str->_CBuf ),用于“无缓冲”。

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

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

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