Where is the STDOUT buffer?

As you know, STDOUT is buffered on Linux. My question is: 1) is this a global buffer shared by all processes? or one buffer for each process? 2) where is the buffer? per stack, or heap or static area? 3) who creates it?

+3


source to share


3 answers


stdout

is a C pointer FILE

generated by the standard library, so the corresponding code is loaded as part of your C library. On Linux it will be implemented in terms of Posix file descriptors.



Both your C library and the kernel can use buffering; you will have to check individual documents. I recommend starting by looking at the relevant part of the C library source code (i.e. the part that implements <stdio.h>

), which should be very educational.

+3


source


The best resource to learn about the C standard library in harrowing detail is PJ Plauger's C standard library . He describes all the problems that came up when he implemented the library himself (in MSWord! On a win3.1 laptop!)!

It also gives details on how to use (and test) each function.

For the Unix (Linux) side, you should start reading about "inode", which is a classic data structure for storing cached files in memory. The classic book for this The UNIX Operating System Design by Maurice J. Bach.


Okay, now that you are appropriately scolded for not reading all the old books and every wiki page associated with them.



Here is a relevant quote from The Standard C Library, p. 256.

Basically, you can exercise some control over how the data is buffered I / O for a stream. However, you should understand that buffering is an optimization based on various assumptions about I / O patterns. These assumptions are usually correct, and many implementations follow your advice. But they don't need it. An implementation can ignore most of your buffering requests.

However, if you think a larger buffer will improve performance, or a smaller buffer will save space, you can provide your own candidate buffer. Call the function setvbuf

after opening the file and before performing any other operations on the stream. (Avoid the older function setbuf

, which is less flexible.) You can specify whether the I / O should be fully buffered, text string buffered, or unbuffered. This can affect how well your program works.

...

setbuf

- use setvbuf

this function instead for more control.

setvbuf

- It is generally best to let the Standard C library decide how to buffer the I / O for you. If you are sure you do not want buffering or line buffering, use this function to properly initialize the stream. Call setvbuf

immediately after opening the stream. Almost any operation on the stream will override your choice of buffering strategy. If you supply your own buffer with this call, don't assume the thread is actually using it. And never change the contents of the buffer while the stream is open. The argument mode (third) must have one of the values _IOFBF

, _IOLBF

or _IONBF

, as described above. Also see the Macro BUFSIZ

described [elsewhere].

...

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

      

So, at least in this implementation, the default buffer probably lives in a FILE structure and is allocated on the heap. Here we see that its sibling, the character buffer ( str->_CBuf

), is used for "unbuffered".

+2


source


It depends on how you write to stdout. If you use stdio

it will be line buffered if the output is piped to the tty. Otherwise, it will be completely buffered.

For details see man stdio

.

If you are using low-level routines such as write

only data bytes are written. Depending on the target, there will be buffering in the kernel. If the target is a tty, it can be written directly to the terminal.

0


source







All Articles