14  Unidad 6: El Caché de E/S en Sistemas Operativos Modernos

Sesión 2: Gestión Dinámica del Page Cache

Autor/a

Luis Torres

Fecha de publicación

23 de julio de 2025

En la sesión anterior se han presentado el funcionamiento del caché, ahora nos toca revisar cómo se gestiona en el sistema operativo. Para eso, el sistema operativo utiliza técnicas y algoritmos dependiendo de los requerimientos de cada caso.

Estos mecanismos son el corazón del rendimiento y la fiabilidad de la E/S. Veremos la “inteligencia” del kernel en acción, gestionando activamente este recurso para maximizar la velocidad y garantizar la seguridad de los datos. Para hacer estos procesos complejos más intuitivos, usaremos una analogía central para cada uno.

14.1 Algoritmo de reemplazo: La biblioteca con espacio limitado

Imagina que tu memoria RAM es una mesa de estudio: de acceso muy rápido, pero con espacio limitado. La biblioteca entera es tu disco duro: inmensa, pero lenta.

El dilema es claro: tu mesa está llena de libros (páginas en caché), pero necesitas traer uno nuevo de la estantería (leer del disco). Debes devolver un libro para hacer espacio. ¿Cuál eliges? No querrás devolver el libro que más consultas. El kernel enfrenta este mismo problema y su solución se llama Reclamo de Páginas (Page Reclaim).

La estrategia de Linux: El LRU de dos listas 📚

En lugar de revisar constantemente qué libro usaste menos (un proceso lento), Linux organiza los libros sobre la mesa en dos pilas:

  1. Pila Inactiva (inactive list): Aquí van los libros nuevos que traes a la mesa. Son candidatos a ser devueltos si no los vuelves a usar pronto.
  2. Pila Activa (active list): Si tomas un libro de la pila inactiva y lo consultas de nuevo (es decir, el flag PG_referenced de la página se activa), el kernel lo considera importante y lo mueve a la pila “activa”.

Cuando se necesita espacio, el kernel siempre toma el libro que ha estado más tiempo en la base de la pila inactiva. De esta forma, protege los libros de uso frecuente y descarta de manera eficiente los que probablemente no se necesiten más.

14.2 Escritura diferida: Dejando los platos sucios para después

Imagina una cocina de restaurante muy concurrida (el Page Cache). Cada vez que un programa modifica datos, es como usar un plato limpio y dejarlo “sucio” (una página marcada como PG_dirty). Sería una locura lavar cada plato en el instante en que se ensucia; se detendría la producción. De la misma manera, el kernel no escribe cada cambio al disco de inmediato.

La estrategia de Linux: Flusher threads 🍽️

El kernel emplea “lavaplatos” (flusher threads), que son procesos que se ejecutan en segundo plano para escribir las páginas sucias al disco en lotes. Se activan por tres motivos:

  • Por Tiempo: Ningún plato puede quedarse sucio más de X segundos. Los flusher threads se activan periódicamente para limpiar los datos “viejos” (controlado por el parámetro de kernel vm.dirty_expire_centisecs).
  • Por Acumulación: Si los platos sucios ocupan demasiado espacio en la cocina (ej. 10% de la memoria, vm.dirty_background_ratio), los lavaplatos empiezan a trabajar para controlar la acumulación.
  • Por Emergencia: Si la cocina está a punto de colapsar por los platos sucios (ej. 20% de la memoria, vm.dirty_ratio), se da la orden de parar casi todo y dedicarse a limpiar. Este es el motivo por el cual el sistema puede experimentar una breve pausa durante operaciones de escritura muy intensas.

14.3 Lectura anticipada: El asistente que se adelanta a tus deseos

Imagina que le pides a tu asistente personal el “Informe Trimestral, Página 1” de un enorme archivador (el disco). Inmediatamente después, le pides la “Página 2”.

El asistente inteligente (el kernel), al notar este patrón de acceso secuencial, no espera. Te entrega la página 2 y, por iniciativa propia, va al archivador y trae las páginas 3, 4 y 5, dejándolas sobre tu escritorio (el Page Cache).

Cuando pides la página 3, la respuesta es instantánea porque ya la tienes a mano. Esta es la lectura anticipada (read-ahead). Es un mecanismo proactivo que mejora drásticamente el rendimiento en la lectura de archivos grandes.

14.4 Control desde el espacio de usuario: El botón de “Guardar ahora”

La estrategia de los “platos sucios” es eficiente, pero arriesgada. Como vimos en la sesión anterior, si hay un apagón repentino, todos los datos en caché que no se habían escrito al disco, se pierden.

Para aplicaciones críticas como una base de datos, la pérdida de datos es inaceptable. Necesitan una forma de ordenarle al sistema que guarde el trabajo de inmediato.

Garantizando la durabilidad con llamadas al sistema 💾

Los programadores tienen “botones de emergencia” para forzar la sincronización del caché con el disco:

  • fsync(): Es el botón de “Guardar” por excelencia. Le dice al kernel: “Para este archivo en particular, escribe todos sus datos y metadatos pendientes al disco AHORA y no me respondas hasta que estés seguro de que la operación se completó”. Es la garantía máxima de durabilidad para un archivo.

  • sync(): Es un botón mucho más drástico: “Guarda TODO lo que esté pendiente en TODO el sistema”. Es menos común y mucho más “pesado” para el rendimiento general del sistema.