Gestión de Memoria

Tipos, Jerarquía, Algoritmos y Optimización

Plataformas Tecnológicas - SPEED

¿Qué es la Gestión de Memoria?

La gestión de memoria es un componente crítico de los sistemas operativos que controla y coordina el uso de la memoria principal (RAM) entre los procesos en ejecución.

En programación, entender cómo funciona la memoria es esencial para escribir código eficiente, especialmente en lenguajes de bajo nivel como C/C++ o en desarrollo de sistemas embebidos.

Dato Importante

Un sistema operativo moderno puede gestionar terabytes de memoria física y virtual, distribuyéndola eficientemente entre cientos de procesos simultáneos.

Jerarquía de Memoria

  • Registros del CPU 1-64 bytes
  • Caché (L1, L2, L3) KB a MB
  • Memoria RAM GB
  • Memoria Virtual (Swap) GB a TB
  • Almacenamiento Persistente TB+

Tipos de Memoria

Comparativa de Tecnologías

Tipo Velocidad Volatilidad Uso Principal
SRAM 1-10 ns Volátil Caché del CPU
DRAM 50-100 ns Volátil Memoria principal
Flash NAND 25-100 μs No volátil Almacenamiento SSD
HDD 5-10 ms No volátil Almacenamiento masivo
RAM

Definición: Memoria de acceso aleatorio volátil para datos activos.

Tipos: DDR4/DDR5
Velocidad: Hasta 6400 MT/s

Alta velocidad de acceso

Volátil (pierde datos sin energía)

Caché

Definición: Memoria pequeña y rápida cerca del CPU.

Niveles: L1, L2, L3
Tamaño: KB a MB

Extremadamente rápida

Muy costosa por byte

Memoria Virtual

Definición: Extensión de la RAM usando almacenamiento.

Ubicación: Disco duro/SSD
Tamaño: 1-4x RAM física

Permite más procesos en memoria

Mucho más lenta que RAM

Memoria No Volátil

Definición: Memoria que persiste sin energía.

Ejemplos: Flash, 3D XPoint
Velocidad: Entre RAM y disco

Persistencia sin energía

Mayor costo que DRAM

Tendencias en Memoria

  • Aumento de capacidades DDR5 (hasta 128GB por módulo)
  • Adopción de memoria no volátil (Optane, CXL)
  • Memoria unificada en sistemas heterogéneos
  • Enfoque en eficiencia energética

Gestión de Memoria en Sistemas Operativos

Los sistemas operativos utilizan diversas técnicas para gestionar eficientemente la memoria entre múltiples procesos.

Fragmentación

Problema: Memoria dividida en partes no contiguas.

Tipos:

  • Fragmentación externa: huecos entre asignaciones
  • Fragmentación interna: espacio no usado dentro de bloques asignados

Solución: Paginación, segmentación, compactación

Paginación

Concepto: Dividir memoria en páginas de tamaño fijo.

Características:

  • Tamaño típico: 4KB (puede variar)
  • Tabla de páginas traduce direcciones lógicas a físicas
  • Elimina fragmentación externa

Ejemplo: x86-64 usa páginas de 4KB con tablas multinivel

Segmentación

Concepto: Dividir memoria en segmentos de tamaño variable.

Características:

  • Cada segmento representa una unidad lógica (código, datos, pila)
  • Tabla de segmentos almacena base y límite
  • Más intuitivo para programadores

Uso: Combinado con paginación en sistemas modernos

Memoria Virtual

Concepto: Extender memoria usando almacenamiento secundario.

Características:

  • Espacio de direcciones mayor que RAM física
  • Páginas se cargan bajo demanda (demand paging)
  • Algoritmos de reemplazo (LRU, FIFO, etc.)

Beneficio: Permite ejecutar más programas de los que caben en RAM

Comparativa de Técnicas

Técnica Ventajas Desventajas Uso típico
Paginación Elimina fragmentación externa, fácil de implementar Fragmentación interna, sobrecarga por tablas Sistemas modernos (Linux, Windows)
Segmentación Más intuitiva, protege segmentos lógicos Fragmentación externa, gestión compleja Antiguos sistemas, combinada con paginación
Memoria Virtual Mayor espacio de direcciones, aislamiento Overhead por paginación, thrashing posible Todos los sistemas modernos

Gestión de Memoria en Programación

Modelos de Gestión

Diferentes lenguajes de programación manejan la memoria de distintas formas, desde automático hasta manual.

// Gestión manual (C)
int *ptr = malloc(sizeof(int)*10); // Asignar
free(ptr);                        // Liberar

// Gestión automática (Java/Python)
List<String> list = new ArrayList<>(); // GC lo limpia

// Ownership (Rust)
let s = String::from("hello"); // Limpieza determinista
Comparativa:
  • Manual (C/C++): Máximo control, riesgo de errores
  • Recolección de basura (Java/Go): Conveniente, overhead
  • Ownership (Rust): Seguridad sin GC, curva de aprendizaje

Problemas Comunes

Errores de memoria son una de las principales causas de vulnerabilidades y fallos en software.

Error Descripción Ejemplo
Memory leak Memoria asignada nunca liberada malloc() sin free()
Dangling pointer Puntero a memoria ya liberada Usar ptr después de free(ptr)
Buffer overflow Escribir fuera de los límites asignados Acceder a array[10] en array de tamaño 5
Use after free Acceder a memoria ya liberada Similar a dangling pointer pero más específico
Herramientas de Detección:
  • Valgrind: Suite de herramientas para depuración de memoria
  • AddressSanitizer (ASan): Detector de errores de memoria en tiempo de ejecución
  • Static Analyzers: Detección estática de posibles errores (Coverity, Clang Analyzer)

Optimización de Memoria

Técnicas de Optimización:
  • Pool de memoria Reducción de fragmentación
  • Objetos inmutables Compartición segura
  • Cache-aware structures Mejor uso de caché
Patrones de Diseño:
  • Flyweight Compartir objetos
  • Object Pool Reutilización
  • Copy-on-Write Optimización de copias
Ejemplo: Pool de Memoria en C++
// Creación de un pool de memoria
class MemoryPool {
private:
    void* pool;
    size_t blockSize;
    size_t poolSize;
    std::vector<void*> freeList;
    
public:
    MemoryPool(size_t blockSize, size_t numBlocks) {
        this->blockSize = blockSize;
        poolSize = blockSize * numBlocks;
        pool = malloc(poolSize);
        
        // Inicializar lista de bloques libres
        for(size_t i = 0; i < numBlocks; i++) {
            freeList.push_back(static_cast<char*>(pool) + i * blockSize);
        }
    }
    
    void* allocate() {
        if(freeList.empty()) return nullptr;
        void* block = freeList.back();
        freeList.pop_back();
        return block;
    }
    
    void deallocate(void* block) {
        freeList.push_back(block);
    }
    
    ~MemoryPool() {
        free(pool);
    }
};

Los pools de memoria reducen la fragmentación y mejoran el rendimiento al evitar llamadas frecuentes a malloc/free.

Casos de Estudio

Gestión de Memoria en Linux

Características Principales:
  • Modelo de memoria basado en páginas (típicamente 4KB)
  • Asignación por buddy system para bloques de páginas
  • Slab allocator para objetos del kernel
  • OOM Killer para manejar situaciones de memoria agotada
Estructuras Clave:
// Estructura page de Linux (simplificada)
struct page {
    unsigned long flags;        // Estado de la página
    atomic_t _count;            // Contador de referencias
    void *virtual;              // Dirección virtual
    struct list_head list;      // Para listas de páginas
};
Comandos Útiles:
  • free -h - Muestra uso de memoria
  • vmstat -s - Estadísticas de memoria virtual
  • pmap -x [PID] - Mapa de memoria de un proceso
  • /proc/meminfo - Información detallada de memoria

Gestión de Memoria en Windows

Características Principales:
  • Espacio de direcciones de 64TB (en sistemas de 64 bits)
  • Heap manager con múltiples heaps por proceso
  • Memory compression desde Windows 10
  • SuperFetch para precargar datos usados frecuentemente
API de Memoria:
// Funciones básicas de la API de Windows
LPVOID VirtualAlloc(           // Reservar/comprometer memoria
    LPVOID lpAddress,
    SIZE_T dwSize,
    DWORD flAllocationType,
    DWORD flProtect);

BOOL VirtualFree(              // Liberar memoria
    LPVOID lpAddress,
    SIZE_T dwSize,
    DWORD dwFreeType);

HANDLE HeapCreate(             // Crear heap privado
    DWORD flOptions,
    SIZE_T dwInitialSize,
    SIZE_T dwMaximumSize);
Herramientas:
  • Task Manager: Vista básica de uso de memoria
  • Resource Monitor: Detalle avanzado de memoria
  • Performance Monitor: Contadores de rendimiento
  • VMMap: Análisis detallado de memoria por proceso
  • WinDbg: Depuración avanzada de memoria

Comparativa: Linux vs Windows

Aspecto Linux Windows
Tamaño de página 4KB (configurable a 2MB/1GB) 4KB (x86/x64), posible usar large pages
Asignación Buddy system + slab allocator Heap manager + Virtual Memory Manager
Swap Particiones o archivos swap Archivo pagefile.sys
OOM Handling OOM Killer selecciona proceso a terminar Memory compression + notificación al usuario
Fragmentación Menor debido a buddy system Más probable en heaps de usuario

Recursos Adicionales

Libros Recomendados

  • "Operating Systems: Three Easy Pieces"

    Remzi H. Arpaci-Dusseau - Capítulos sobre memoria virtual

  • "Windows Internals" (7th Edition)

    Mark Russinovich - Gestión de memoria en Windows

  • "Understanding the Linux Kernel"

    Daniel P. Bovet - Gestión de memoria en Linux