2013-02-18 79 views
3

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

+8

你为什么在意? – StoryTeller 2013-02-18 10:02:06

+1

我的理解是它是由内核堆区内的内核创建的,然后可以通过/ dev/stdout访问。 'MSWord!'中的' – slugonamission 2013-02-18 10:02:28

回答

3

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

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

2

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

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

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


好吧,现在你已经适当地因没有阅读所有旧书和每一个相关的维基页面而被骂。

以下是的相关报价标准C库,第53页。 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); 
    } 

因此,在这个实现至少,默认缓冲区可能住在文件的结构和在堆中分配。我们可以在这里看到它的兄弟,字符缓冲区(str->_CBuf),用于“无缓冲”。

+0

!' - 什么?! – n611x007 2013-07-02 10:31:09

+0

他没有合适的文本编辑器。 – 2013-07-02 20:24:21

0

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

另请参阅man stdio了解更多详情。

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

相关问题