¿Cuáles son las reglas del tampón stdout de lavado automático en C?

Solo tengo curiosidad por las condiciones que deben cumplirse para eliminar automáticamente el buffer de stdout.

En primer lugar, estaba confundido de que este pseudo código no imprime cada iteración:

while (1) { printf("Any text"); sleep(1); } 

Pero si agrego un carácter de nueva línea, lo hará.

Después de algunos experimentos, encontré que en mi máquina el buffer de stdout está enrojecido:

  1. Cuando pongo a stdout 1025 caracteres o más;
  2. Cuando leo stdin;
  3. Cuando puse el carácter de nueva línea en stdout;

La primera condición es totalmente clara: cuando el buffer está lleno, debe enjuagarse. El segundo también es razonable. Pero, ¿por qué el carácter de nueva línea causa enrojecimiento? ¿Cuáles son las otras condiciones implícitas para esto?

Las reglas del búfer stdout de barrido automático están definidas por la implementación (ID). Es ID cuando la transmisión está sin búfer , totalmente en búfer o en línea con búfer .

Cuando una secuencia está sin búfer , los caracteres están destinados a aparecer desde la fuente o en el destino lo antes posible. De lo contrario, los caracteres se pueden acumular y transmitir ao desde el entorno del host como un bloque.

Cuando una secuencia está totalmente almacenada en el búfer , los caracteres están destinados a ser transmitidos hacia o desde el entorno del host como un bloque cuando se llena un búfer.

Cuando un flujo se almacena en línea , los caracteres están destinados a ser transmitidos hacia o desde el entorno de host como un bloque cuando se encuentra un carácter de nueva línea. Además, los caracteres están destinados a transmitirse como un bloque al entorno de host cuando se llena un búfer, cuando se solicita entrada en un flujo sin búfer o cuando se solicita entrada en un flujo de búfer de línea que requiere la transmisión de caracteres del entorno de host .

El soporte para estas características está definido por implementación , … C11dr §7.21.3 3


Solo tengo curiosidad por las condiciones que deben cumplirse para eliminar automáticamente el buffer de stdout.

Si el código quiere asegurarse de que la salida se fflush() , utilice fflush() . Otras condiciones que pueden vaciar automáticamente la secuencia están definidas por la implementación.

Consulte la página man para setbuf(3) . Por defecto, stdout está configurado en el modo de buffer de línea.

printf() y sus variantes funcionan con salida almacenada y delegada a write() . Así que este almacenamiento en búfer está controlado por la implementación de la biblioteca C de printf , con la configuración del búfer y el búfer ubicados en la estructura de FILE .

También vale la pena notar la diferencia entre la sección 3 y la sección 2 de las páginas del manual de Unix. La Sección 2 está compuesta por llamadas a funciones que hablan directamente con el sistema operativo y hacen cosas que de otro modo serían imposibles de hacer desde un progtwig de usuario puro. La Sección 3 está compuesta por llamadas a funciones que un usuario podría reproducir por su cuenta, que a menudo delegan en llamadas de la sección 2. Las funciones de la Sección 2 contienen la “magia” de bajo nivel que permite a los progtwigs C interactuar con el mundo exterior y realizar E / S. Las funciones de la Sección 3 pueden proporcionar una interfaz más conveniente para las funciones de la sección 2.

printf , scanf , getchar , fputs y otras funciones FILE * son todas funciones de la sección 3 que delegan en write() y read() , que son funciones de la sección 2. read() y write() no almacenan en búfer. printf() interactúa con el búfer en la estructura de FILE y ocasionalmente decide enviar el contenido de ese búfer a través de write() .

  • Un flujo de salida que está almacenado en la línea se enjuagará siempre que se produzca una nueva línea.

  • Una implementación puede (aunque no se requiere) enjuagar todas las secuencias de salida de buffer de línea siempre que se intente una lectura desde cualquier flujo de entrada de buffer de línea.

  • Las implementaciones no pueden hacer que las transmisiones estén completamente almacenadas de manera predeterminada a menos que se pueda determinar que no están asociadas con un “dispositivo interactivo”. Por lo tanto, cuando stdin / stdout son terminales, no pueden ser completamente almacenados en búfer, solo almacenados en búfer de línea (o sin búfer).

Si solo necesita enjuagar cuando la salida es a un terminal, es suficiente suponer que al escribir una nueva línea se produce un enrojecimiento. De lo contrario, debe llamar explícitamente a fflush donde sea que necesite enjuagar.

Hay muchas circunstancias en que la salida almacenada en un flujo se descarga automáticamente:

  1. Cuando intenta hacer salida y el buffer de salida está lleno.
  2. Cuando la stream está cerrada.
  3. Cuando el progtwig termina llamando a exit.
  4. Cuando se escribe una nueva línea, si la transmisión se almacena en línea.
  5. Cada vez que una operación de entrada en cualquier secuencia realmente lee datos de su archivo.

stdout es buffer de línea por defecto.

Si desea vaciar la salida almacenada temporalmente en otro momento, puede llamar a fflush.

Estándar en línea C2011

7.21.3 Archivos

3 Cuando una secuencia está sin búfer , los caracteres están destinados a aparecer desde la fuente o en el destino lo antes posible. De lo contrario, los caracteres se pueden acumular y transmitir ao desde el entorno del host como un bloque. Cuando una secuencia está totalmente almacenada en el búfer , los caracteres están destinados a ser transmitidos hacia o desde el entorno del host como un bloque cuando se llena un búfer. Cuando un flujo se almacena en línea , los caracteres están destinados a ser transmitidos hacia o desde el entorno de host como un bloque cuando se encuentra un carácter de nueva línea. Además, los caracteres están destinados a transmitirse como un bloque al entorno de host cuando se llena un búfer, cuando se solicita entrada en un flujo sin búfer o cuando se solicita entrada en un flujo de búfer de línea que requiere la transmisión de caracteres del entorno de host . El soporte para estas características está definido por la implementación y puede verse afectado por las funciones setbuf y setvbuf .

7 Al inicio del progtwig, tres flujos de texto están predefinidos y no necesitan abrirse explícitamente: entrada estándar (para leer la entrada convencional), salida estándar (para escribir salida convencional) y error estándar (para escribir la salida de diagnóstico). Como se abrió inicialmente, el flujo de error estándar no está completamente almacenado en el búfer; la entrada estándar y las secuencias de salida estándar están completamente almacenadas en el búfer si y solo si se puede determinar que la transmisión no se refiere a un dispositivo interactivo.

Por lo tanto, una línea de flujo en búfer se tirará en una nueva línea. En la mayoría de los sistemas con los que tengo experiencia, stdout está almacenado en línea en una sesión interactiva.