Sesión 9
Almacenamiento Primario y Secundario

Memoria Virtual, Archivos y Directorios

Navegación: F pantalla completa

Unidad 2 - Sistemas Operativos

El problema del almacenamiento

¿Dónde viven los procesos?

En la Unidad 1 analizamos cómo la CPU ejecuta procesos (FCFS, SJF, RR). Sin embargo, omitimos una pregunta crítica: ¿De dónde saca la CPU las instrucciones y los datos?

  • La CPU no puede ejecutar un programa directamente desde el disco duro.
  • Todo programa debe convertirse en proceso y cargarse en la Memoria Principal (RAM).
  • Pero la RAM es limitada, costosa y volátil. El disco es masivo, barato y persistente.

El Rol del SO: Orquestar el movimiento de datos entre medios lentos/masivos y medios rápidos/limitados de manera transparente para el usuario y el programador.

Fundamentos de Hardware

La Jerarquía de Memoria

Los sistemas organizan el almacenamiento en una pirámide de compromiso entre Velocidad vs. Capacidad y Costo:

  1. Registros de CPU: Bytes. Velocidad de reloj.
  2. Memoria Caché: Megabytes. En el procesador.
  3. Memoria RAM: Gigabytes. Direccionable por bytes.
  4. Almacenamiento: Terabytes. Direccionable por bloques.

Principio de Localidad:

  • Espacial: Si accedes a una dirección, pronto accederás a las contiguas (Carga de Bloques).
  • Temporal: Si accedes a un dato, es probable que vuelvas a usarlo (Caché).
Fundamentos de Hardware

El Abismo de la Latencia

Escale los tiempos de acceso a tiempos comprensibles para un humano (asumiendo 1 ciclo de CPU = 1 segundo):

Medio de almacenamientoTiempo real aprox.A escala humana
Registro de CPU0.3 ns1 segundo
Caché L11 ns3 segundos
Memoria RAM100 ns3 minutos
Disco SSD (NVMe)20,000 ns14 horas
Disco Mecánico (HDD)10,000,000 ns¡10 Meses!

Reflexión: Cuando un proceso necesita un dato del disco (un "Page Fault"), la CPU tiene que esperar una eternidad. Por eso el proceso pasa a Waiting.

Memoria Principal (RAM)

Espacio de Direccionamiento Físico

La RAM es una secuencia enorme de bytes, cada uno con una dirección física única. El procesador pone esta dirección en el bus para leer o escribir.

Limitaciones reales:

  • Es un recurso escaso (Ej. PC con 8GB de RAM).
  • Un solo IDE puede requerir 12GB.
  • ¿Cómo evitamos el colapso si pedimos más RAM de la que existe?

Problema de multiprogramación:

  • Si P1 y P2 están en RAM, ¿cómo garantizamos seguridad?
  • ¿Cómo evitamos que un bug en P1 sobreescriba a P2?
El concepto clave

Memoria Virtual: La gran ilusión

El SO, con ayuda de la unidad MMU del hardware, crea una abstracción llamada Memoria Virtual.

  • Aislamiento: Cada proceso cree que tiene su propia memoria completa (iniciando en 0). No sabe de otros procesos.
  • Direcciones Lógicas vs Físicas: Tu código trabaja siempre con direcciones lógicas. La MMU las traduce a direcciones físicas reales.
  • Expansión (Swap): Lo que no cabe en RAM física, se guarda temporalmente en el Disco Duro (Archivo de paginación o Swap).
Técnicas de Administración

Paginación (Paging) bajo el capó

Para gestionar la ilusión sin fragmentar, el SO mueve bloques fijos enteros:

  • Páginas (Pages): La memoria virtual del proceso se divide en bloques (típicamente 4 KB).
  • Marcos (Frames): La RAM física se divide en contenedores del mismo tamaño.
  • Tabla de Páginas: Un diccionario (en el PCB) que mapea la Página Lógica al Marco Físico.
Proceso A (Lógicas) Pag 0: [Main] -> Marco 5 (RAM) Pag 1: [Variables] -> Marco 12 (RAM) Pag 2: [Textura 4K]-> No mapeado! (Disco) Proceso B (Lógicas) Pag 0: [Main] -> Marco 2 (RAM)
Rendimiento y UX

Fallos de Página y Thrashing

¿Qué pasa si el programa lee la "Página 2" (enviada al disco para ahorrar espacio)?

  1. El procesador lanza una interrupción (Page Fault Trap).
  2. El SO bloquea el proceso, busca la página en disco y la carga en un Marco libre de RAM.
  3. Mientras el disco gira, el SO da la CPU a otro proceso. Al finalizar, reanuda el original.

Thrashing (Hiperpaginación): Ocurre cuando hay tan poca RAM libre que el sistema pasa más tiempo intercambiando páginas con el disco que ejecutando código. El PC "se congela".

Persistencia

Del mundo volátil al persistente

Para conservar código y datos tras apagar el equipo, necesitamos Almacenamiento Secundario.

Sin embargo, el hardware del disco (HDD/SSD) solo entiende de Bloques físicos y arreglos de bytes. Trabajar enviando bytes al "Bloque físico 4,091,822" es imposible para un desarrollador.

Solución del SO: Crear otra abstracción masiva llamada Sistema de Archivos (File System). Convierte bloques en entidades lógicas llamadas Archivos y Directorios.

Conceptos Lógicos

¿Qué es exactamente un Archivo?

Un archivo es una unidad lógica de almacenamiento nombrada. El Sistema de Archivos lo divide internamente en dos estructuras críticas:

1. El Contenido (Payload):

La secuencia de bytes real (el texto de tu código C#, los pixeles de tu .png). Puede estar fragmentado por el disco duro.

2. Los Metadatos (Inodo/FCB):

Estructura gestionada por el SO que almacena la "receta" de cómo reconstruir y proteger el contenido.

Metadatos de Archivos

Atributos Básicos

Esta "receta" administrada por el Kernel (ej. ext4, NTFS) incluye:

  • Nombre: El identificador legible (con o sin extensión obligatoria).
  • Identificador único: El Inode Number (solo en Linux/Unix).
  • Punteros de ubicación: Lista de direcciones de bloque físico.
  • Tamaño Real vs Ocupado: Bytes vs Bloques reservados.
  • Permisos (r, w, x): Listas de control de acceso (Quién puede leer, escribir o ejecutar). *Vital para Shell*.
  • Marcas de tiempo: Creación, Último acceso (atime) y Modificación (mtime).
Interfaz del Programador (API)

Syscalls: Operaciones Universales

Un proceso no toca el disco, le pide al SO mediante Llamadas al Sistema:

  • Open(): Copia metadatos a la RAM y devuelve un Handle.
  • Read() / Write(): Transfiere memoria usando el Handle.
  • Seek(): Mueve el puntero lógico.
  • Close(): Destruye el Handle y voltea buffers a disco.
// PYTHON f = open("datos.csv", "w") # Open f.write("PID,CPU") # Write f.close() # Close // C (El padre de todo) int fd = open("datos.csv", O_WRONLY); write(fd, "PID,CPU", 7); close(fd);
Estructura Lógica

Directorios (Carpetas)

Tener 2 millones de archivos en una sola lista plana haría la búsqueda (Open) insoportablemente lenta. Los directorios resuelven esto agrupando lógicamente.

Verdad técnica: Un directorio es solo un Archivo Especial. Si abres el código binario de una "carpeta", solo verás una tabla de texto con dos columnas: [Nombre de archivo] -> [Puntero al Inodo].

  • Permiten organización jerárquica en forma de árbol invertido.
  • Permiten archivos homónimos (ej. `main.cs`) siempre que sus "tablas padre" sean distintas.
Navegación

Rutas (Paths) - El mapa del tesoro

Ruta Absoluta:
Inicia desde la raíz del disco. Es inmutable.

# Linux /home/user/proyecto/src/main.cs # Windows C:\Users\user\proyecto\src\main.cs

Ruta Relativa:
Inicia desde el Directorio de Trabajo Actual (CWD) en RAM. Portable.

# Desde 'proyecto' ./src/main.cs # Subiendo un nivel ../logs/error.log

Variables de Directorio Especiales:
. (Un punto) = Directorio actual.
.. (Dos puntos) = Padre jerárquico del directorio actual.

Rendimiento en Programación

Leer archivos masivos vs RAM

Analicemos un error crítico de código al procesar bases de datos masivas (ej. CSV de 4GB):

// MALA PRÁCTICA: Pedir al SO traer todo a Memoria Virtual // Python contenido = open("base_datos_4GB.csv").read() // C# string cont = File.ReadAllText("base_datos_4GB.csv"); // Consecuencia: Crash por OutOfMemory o Thrashing.

Fallo de diseño: Forzamos a la MMU a encontrar 4GB de páginas lógicas contiguas en RAM para un proceso que tal vez solo necesita leer línea por línea.

Rendimiento en Programación

Solución: Streams y Buffers

La forma correcta de leer sin destruir la memoria virtual es usar Flujos (Streams):

// BUENA PRÁCTICA: Buffer cíclico // C# using (StreamReader sr = new StreamReader("datos_4GB.csv")) { string linea; while ((linea = sr.ReadLine()) != null) { Analizar(linea); } } # Python with open("datos_4GB.csv", "r") as f: for linea in f: # Iterador por stream analizar(linea)

El Sistema de Archivos lee un bloque del disco a la RAM, el programa lo procesa, y el SO reutiliza ese mismo espacio de RAM para cargar el siguiente. Impacto RAM: Casi Cero.

Ejemplo Integrador (Proyecto E2)

Arquitectura Lógica del Gestor

Para la E2, el Gestor de Procesos no usará datos quemados. Diseñaremos una estructura lógica que el SO entienda:

Árbol de Directorios:

Equipo05-SO/ ├── src/ │ └── Program.cs ├── data/ <-- Lectura │ └── procesos.csv └── logs/ <-- Escritura └── sistema.log

Interacciones del Proceso:

  1. Usuario ejecuta, SO carga a Memoria Virtual.
  2. Código hace Open leyendo ruta relativa ../data/procesos.csv (Modo Read).
  3. Inicia simulación, escribiendo estado en ../logs/sistema.log.
Ejemplo Integrador (Proyecto E2)

Modos de Apertura: Sistema de Logs

Si abres el archivo log en modo Escritura ("w"), el SO borra el archivo cada vez que inicia el programa. Debemos usar Modo Anexar (Append/"a").

# PYTHON - Helper import time def log_evento(msg): with open("logs/sys.log", "a") as f: ts = time.strftime("%H:%M:%S") f.write(f"[{ts}] {msg}\n") log_evento("P1 pasa a CPU")
// C# - Método using System.IO; static void LogEvento(string msj) { string r = "logs/sys.log"; string ts = DateTime.Now.ToString("T"); File.AppendAllText(r, $"[{ts}] {msj}\n"); } LogEvento("P2 expulsado");
El problema invisible del Kernel

File Buffering y Flush()

Cuando el código hace f.write("P1 finalizado"), ¿El dato llega inmediatamente al disco magnético?

NO. Escribir cada letra físicamente mataría el rendimiento. El Kernel "miente": Guarda el texto en un segmento de RAM oculto (Buffer del FS) y le dice a tu programa "Ya lo guardé".

  • El SO espera a que el Buffer se llene para volcarlo al disco de un golpe (Flush).
  • Riesgo: Si hay pantallazo azul, el log que estaba en el buffer volátil se pierde.
  • En aplicaciones financieras, el programador invoca f.flush() para forzar al disco.
Resumen de la Sesión

Conceptos Base Unidad 2

DominioPropósito Fundamental en el SO
Memoria Virtual (MMU)Aislar procesos y evitar colapsos por falta de RAM física mediante Traducción y Paginación (Swap).
Archivos (Files)Enmascarar estructuras físicas crudas como bloques lógicos con Datos + Atributos.
Directorios y RutasÁrbol relacional (Archivo Especial) para búsquedas. Exige uso de Rutas Relativas.
Flujos (Streams)Puente de amortiguación entre RAM y Discos para no colapsar la memoria al leer datos pesados.