Programación concurrente en Linux

# Buffers de entrada/salida

Las llamadas al sistema de entrada-salida de UNIX/Linux siguen un modelo muy sencillo orientado al byte. `read()` y `write()` leen y escriben un número de bytes, sin más consideraciones acerca del formato. Si el programador tiene que manejar objetos de entrada/salida de diferentes tipos, como cadenas de caracteres o números, necesita algo más cómodo. Las bibliotecas de entrada/salida, en concreto la biblioteca estándar de C, existen para facilitar la vida al programador, suavizando la sintaxis de las llamadas al sistema y proporcionando mecanismos para manejar cómodamente formatos y tipos de datos.

Supón que te piden que construyas una función como `scanf` para un lenguaje que carece de biblioteca de entrada/salida. Está claro que tienes que echar mano de la llamada al sistema `read()`. Enseguida te plantearás la siguiente cuestión: para leer un dato de un formato determinado, por ejemplo un número o un string, ¿cuántos bytes debería leer en la llamada `write()`?

Una respuesta a esta respuesta podría ser: de uno en uno, como en `stee`. Ten en cuenta, sin embargo, que cada llamada al sistema operativo supone cierto trabajo extra, como ya vimos. Es cierto que los procesadores de hoy en día son muy rápidos y manejan con mucha agilidad el cambio de modo de operación, el acceso al vector de interrupciones y el cambio de contexto en la pila, pero `scanf()` y `printf()` se diseñaron hace casi medio siglo, cuando los procesadores eran mucho más lentos. Además, si la entrada/salida se hace sobre un fichero en el disco, el acceso es por bloques.

De modo que los diseñadores optaron por molestar las menos veces posible al sistema operativo, e implementaron buffers de cierto tamaño que se llenan de una vez:

    read(0, buffer, TAM_BUFFER);

para que luego las llamadas a `scanf()` entreguen el contenido del buffer hasta agotarlo. Lo mismo es aplicable a `printf()`.

Esto es exactamente lo que hacemos en nuestra vida diaria. Si nos preparamos un café y queremos echarle un par de azucarillos, compraremos un paquete de cien. Ir a la tienda tiene un coste, así que inconscientemente optimizamos nuestra estrategia: minimizamos el número de visitas a la tienda, pero no nos traeremos tantos azucarillos que no podamos almacenar, o quizás cambie nuestro gusto y dejemos de echar azúcar al café y no lleguemos a gastarlos…

¿Es realmente más eficiente utilizar la biblioteca? Si no has obtenido resultados concluyentes en tus experimentos, quizás debamos suponer que el sistema operativo también pone algo de su parte, como veremos.