13 Unidad 6: El Caché de E/S en Sistemas Operativos Modernos
Sesión 1: Fundamentos del Caché y la Arquitectura de Linux
13.1 Introducción: El problema de la latencia y la necesidad del caching
En el núcleo del diseño de cualquier sistema operativo moderno yace una tensión fundamental: la disparidad de velocidad entre los componentes del sistema. Para ponerlo en perspectiva con una analogía: si una operación de la CPU tomara un segundo de nuestro tiempo, leer de la RAM sería como esperar unos pocos segundos más. Sin embargo, leer de un SSD equivaldría a esperar varias horas, y ¡leer de un disco duro magnético podría tomar varias semanas!
- CPU y RAM: Operan en la escala de nanosegundos (10⁻⁹ s).
- SSD (Unidad de Estado Sólido): Acceden en microsegundos (10⁻⁶ s).
- HDD (Disco Duro Magnético): Acceden en milisegundos (10⁻³ s).
Esta brecha, que abarca de 3 a 6 órdenes de magnitud, significa que si cada solicitud de datos requiriera un acceso físico al disco, la CPU pasaría la mayor parte de su tiempo inactiva. El rendimiento del sistema estaría limitado por su componente más lento. Para mitigar este cuello de botella, el caching no es una característica opcional, sino una necesidad de diseño ineludible.
La idea central es simple: mantener una copia de los datos a los que se ha accedido recientemente desde el disco en una región de la memoria principal (RAM), que es mucho más rápida. Si los datos están presentes (cache hit), se entregan inmediatamente. Si no lo están (cache miss), el kernel los lee del disco, los entrega y guarda una copia en el caché para el futuro.
Este mecanismo se fundamenta en el principio de localidad, una observación empírica del comportamiento de los programas:
- Localidad Temporal: Si se accede a un dato, es probable que se vuelva a acceder a él pronto. Mantenerlo en caché explota esta propiedad.
- Localidad Espacial: Si se accede a un dato, es probable que se accedan a datos en ubicaciones cercanas. Esto justifica estrategias como el read-ahead, donde el kernel lee bloques contiguos por adelantado.
13.2 El Page Cache de Linux: Una arquitectura unificada
Mientras que sistemas Unix tradicionales (System V) usaban un “buffer caché” separado para los bloques de disco y un “page cache” para los archivos, esto generaba ineficiencias y el problema del “doble caché” (el mismo dato podía estar cacheado dos veces).
Linux evolucionó hacia una arquitectura unificada conocida como el Page Cache.
En Linux, el Page Cache es el único caché de disco. Almacena páginas de memoria que pueden contener: - Datos de archivos leídos por read()
. - Datos de archivos escritos por write()
. - Páginas de archivos mapeados en memoria (mmap
). - Metadatos del sistema de archivos.
Esta unificación elimina la redundancia, simplifica la gestión y asegura que toda la RAM libre esté disponible para acelerar las operaciones de E/S de la manera más flexible posible.
13.2.1 La estructura del Page Cache: Páginas y address_space
La unidad fundamental es la página (generalmente 4KB), la unidad básica de gestión de memoria del kernel. Para organizar estas páginas, Linux utiliza dos conceptos clave:
struct page
: Cada página física en el sistema tiene una estructura de metadatosstruct page
que la describe. Contiene información vital como su estado (flags), un contador de uso y, lo más importante, un puntero a suaddress_space
y suindex
dentro de él.struct address_space
: Esta es la estructura del kernel que establece la conexión entre un objeto capaz de contener datos (normalmente un archivo, representado por uninode
) y las páginas en el Page Cache que contienen dichos datos. Eladdress_space
utiliza una estructura de datos optimizada para localizar rápidamente si una página específica de un archivo ya se encuentra en memoria.
13.3 Estados de una página y su ciclo de vida
El campo flags
en struct page
codifica el estado de una página. Este estado es dinámico y crucial para la coherencia y el rendimiento. Los flags más importantes son:
PG_locked
(Bloqueada): El kernel está operando sobre la página (ej. durante una E/S). Actúa como un lock para prevenir condiciones de carrera. Ningún otro proceso puede usarla hasta que se libere.PG_dirty
(Sucia): La página en memoria ha sido modificada, pero los cambios aún no se han escrito en el disco. Esta es la base de la escritura retardada (delayed write
). El kernel retrasa la escritura para agrupar múltiples cambios en una sola operación de E/S física.
La optimización de PG_dirty
introduce un riesgo: si el sistema falla antes de que la página se sincronice con el disco (se escriba), los cambios se perderán, lo que podría dejar el sistema de archivos en un estado inconsistente. Demonios del kernel como flusher threads
se encargan de escribir estas páginas periódicamente.
PG_writeback
(Escritura en Progreso): Se ha iniciado una operación de E/S para escribir el contenido de esta página “sucia” en el disco. La página también estáPG_locked
durante este tiempo.PG_uptodate
(Datos Válidos): La página contiene una copia válida y actualizada de los datos del disco. Una operación de lectura no se completa hasta que este flag está activo.PG_referenced
(Referenciada): Indica que la página ha sido accedida recientemente. Es fundamental para los algoritmos de reemplazo.