meteo-01 arranca solo, meteo-api está active (running), el temporizador del agregador se dispara puntualmente y systemctl list-units --failed no devuelve nada. Y aun así, los usuarios dicen que la API va lenta. Ninguna de las herramientas de la lección anterior responde a la pregunta "¿por qué?", porque todas contestan a "¿está funcionando?" y no a "¿funciona bien?".
Esta lección enseña lo segundo, y lo hace en un orden deliberado: primero el método, después las herramientas. La razón es que la mayoría de los diagnósticos fallidos no fallan por desconocer un comando, sino por saltar a conclusiones: se ve la carga alta, se culpa a la CPU, se añaden núcleos y el problema sigue porque en realidad era la cola del disco. Un método evita eso. Verás dos metodologías con nombre y apellidos —USE y RED—, la lista de comprobación de los primeros 60 segundos que aplicarás siempre igual, y luego, recurso por recurso, qué mide de verdad cada número que te devuelven top, free, iostat, ss y vmstat, con las trampas de interpretación que engañan a casi todo el mundo. Terminaremos subiendo un escalón: de mirar una máquina a instrumentar una flota, y con un laboratorio en el que provocarás cada tipo de saturación para verla con tus propios ojos.
El caso integrado, donde todo esto se aplica a un incidente real de madrugada, es la lección siguiente y última del curso.
Contenido
- Síntoma, causa y línea base
- Dos metodologías: USE y RED
- La lista de comprobación de los primeros 60 segundos
- CPU: qué mide de verdad cada número
- Memoria: por qué
free -hconfunde a todo el mundo - E/S:
iostat -xcampo a campo - Red: colas, retransmisiones y latencia
- Presión de recursos: PSI
- Observación profunda y su coste:
strace,perf, eBPF - Los registros como fuente de diagnóstico
- De la observación puntual a la monitorización continua
- Alertas útiles, SLI y SLO
- Planificación de capacidad
- Laboratorio guiado: provocar y observar cada saturación
Síntoma, causa y línea base
Un síntoma es lo que se percibe: "la web va lenta", "los informes llegan tarde", "la aplicación da errores 502". Una causa es un mecanismo concreto y comprobable: "el agregador está haciendo lecturas aleatorias de 4 KB y la cola del RAID 1 está en 18 peticiones pendientes con 40 ms de espera media". Entre ambos hay una cadena de hallazgos, y el trabajo de diagnóstico consiste en recorrerla descartando en lugar de adivinando.
Tres reglas que evitan la mayoría de los errores:
- Cuantifica el síntoma antes de tocar nada. "Va lenta" no es un dato. "El p99 de
/v1/lecturasha pasado de 80 ms a 4,2 s desde las 03:05, con el mismo volumen de peticiones" sí lo es, y además te da un instante de inicio con el que correlacionar todo lo demás. - Una hipótesis, una comprobación. Cambia una cosa cada vez. Si aplicas tres mitigaciones a la vez y mejora, no sabrás cuál funcionó ni podrás escribir un post mortem honesto.
- Anota con marca de tiempo. Qué mirabas, qué viste y qué hiciste. En un incidente largo, la memoria falla y las salidas de los comandos son irrepetibles.
Y por encima de todo está la línea base. Un número aislado no significa nada: una carga media de 6 puede ser normal en una máquina de 16 núcleos y catastrófica en una de 2. Que el %util del disco esté al 60 % puede ser lo habitual a mediodía. Sin saber cómo se comporta meteo-01 un martes normal, cualquier medición durante el incidente es ruido. Por eso el mejor momento para preparar un diagnóstico es cuando todo va bien: si aún no tienes monitorización continua, guarda al menos una foto periódica.
# Línea base rudimentaria pero utilísima: una foto cada 5 minutos
{ date -Is; uptime; vmstat 1 3 | tail -1; free -m | sed -n 2p; \
iostat -x 1 2 /dev/md0 | tail -3; ss -s | head -2; } >> /var/log/meteora/baseline.logQué hace. Vuelca en un solo fichero, con marca de tiempo ISO, la carga, un muestreo de vmstat (el primer registro de estas herramientas son medias desde el arranque y hay que descartarlo, de ahí el tail -1), la memoria, la actividad del RAID y el resumen de sockets. Ejecutado desde un temporizador de systemd cada 5 minutos, en una semana tienes una referencia con la que comparar. Cuesta unos pocos kilobytes al día y ha salvado más incidentes que muchos paneles.
Dos metodologías: USE y RED
USE (Brendan Gregg) se aplica recurso por recurso y responde a "¿qué componente del sistema está limitando?". Para cada uno se miran tres cosas:
- Utilización: qué fracción del tiempo el recurso está ocupado.
- Saturación: cuánto trabajo está esperando en cola porque el recurso no da abasto.
- Errores: fallos contados por el recurso.
La saturación es la métrica clave y la que más se ignora. Un disco al 100 % de utilización con cola 1 está trabajando a gusto; el mismo disco al 100 % con cola 30 está ahogado. La utilización tiene un techo (100 %) y por eso deja de informar en cuanto lo alcanza; la saturación no tiene techo y sigue creciendo con la gravedad del problema.
RED se aplica al servicio y responde a "¿lo están pasando mal los usuarios?": Rate (peticiones por segundo), Errors (cuántas fallan) y Duration (cuánto tardan, en percentiles). Es la vista desde fuera; USE es la vista desde dentro. Se usan juntas: RED detecta y delimita el problema, USE localiza el recurso culpable.
El flujo completo, que es el que seguirás en la lección siguiente:
graph LR
A["Síntoma<br/>'la API va lenta'"] --> B["RED: cuantificar<br/>p99, tasa, errores"]
B --> C["¿Cuándo empezó?<br/>ventana temporal"]
C --> D["USE recurso a recurso<br/>60 segundos"]
D --> E["Recurso saturado<br/>(cola, no utilización)"]
E --> F["¿Qué proceso?<br/>pidstat, iotop, perf"]
F --> G["Causa concreta<br/>y mitigación medible"]
Tabla de aplicación a meteo-01:
| Recurso | Utilización | Saturación | Errores |
|---|---|---|---|
| CPU | %us+%sy en mpstat -P ALL 1 |
Carga media, procs r de vmstat, /proc/pressure/cpu |
Poco habituales (mcelog) |
| Memoria | MemAvailable en /proc/meminfo |
si/so de vmstat, /proc/pressure/memory |
Muertes del OOM killer en dmesg |
Disco (/dev/md0) |
%util de iostat -x |
aqu-sz, await, /proc/pressure/io |
dmesg (errores de E/S), mdadm --detail |
| Red | rxkB/s/txkB/s en sar -n DEV |
Cola de escucha llena, netstat -s |
ip -s link (errors, dropped) |
Servicio meteo-api |
Peticiones/s | Cola de conexiones (Recv-Q del socket de escucha) |
Códigos 5xx en meteo-api.log |
La lista de comprobación de los primeros 60 segundos
Esta secuencia se ejecuta siempre igual, en el mismo orden, sin pensar. Su valor no es que encuentre la causa, sino que en un minuto descarta el 80 % de las posibilidades y te dice hacia dónde profundizar.
uptime # 1. ¿Cuánta carga hay y desde cuándo?
dmesg -T | tail -30 # 2. ¿Ha gritado el núcleo? (OOM, errores de disco, RAID)
vmstat 1 5 # 3. Vista global: CPU, memoria, intercambio, E/S, contexto
mpstat -P ALL 1 3 # 4. ¿La carga está repartida o hay un núcleo saturado?
pidstat 1 3 # 5. ¿Qué procesos consumen CPU, ahora, por segundo?
iostat -xz 1 3 # 6. ¿Están saturados los discos?
free -m # 7. ¿Hay memoria disponible de verdad?
ss -s # 8. ¿Cuántas conexiones y en qué estado?
sar -n DEV 1 3 # 9. ¿Cuánto tráfico de red?
cat /proc/pressure/* # 10. ¿Quién está causando esperas? (PSI)
systemctl list-units --failed ; journalctl -p err -b --since '-30 min'Qué se busca en cada uno, que es lo que realmente importa:
uptime— las tres cargas medias (1, 5 y 15 minutos). Lo informativo no es el número, sino la tendencia: si es24.1, 8.4, 3.2, el problema está empezando ahora; si es3.2, 8.4, 24.1, ya está remitiendo. También confirma si la máquina se ha reiniciado hace poco.dmesg -T— es lo primero que hay que mirar porque contiene los fallos que ninguna otra herramienta enseña: una muerte por OOM killer, un disco con errores de lectura, un RAID degradado, un desbordamiento de la tabla de conexiones. Un solo mensaje aquí puede terminar el diagnóstico en 10 segundos.vmstat 1 5— la panorámica.res la cola de ejecución (procesos listos esperando CPU);blos bloqueados en E/S ininterrumpible;si/soel intercambio;us/sy/id/wael reparto de CPU;cslos cambios de contexto de 02-01.mpstat -P ALL 1 3— distingue "toda la máquina saturada" de "un solo núcleo al 100 % y quince ociosos", que es el síntoma de un programa monohilo o de una interrupción mal repartida (02-07).pidstat 1 3— a diferencia deps, muestra consumo por intervalo, no acumulado desde el arranque. Es la diferencia entre "este proceso ha usado 40 horas de CPU en dos meses" y "este proceso está usando el 180 % ahora".iostat -xz 1 3—-zomite los dispositivos sin actividad, dejando solo lo interesante.free -m— con la advertencia de la sección de memoria: miraavailable, nofree.ss -s— resumen de sockets; un salto entimewaito en conexiones sincronizadas apunta a la red o al patrón de clientes.sar -n DEV 1 3— tráfico por interfaz, para descartar saturación de enlace.- PSI — la respuesta directa a "¿cuánto tiempo se está perdiendo esperando cada recurso?".
Y siempre, al final, los registros: unidades fallidas y errores recientes del diario.
CPU: qué mide de verdad cada número
La carga media no es utilización de CPU. Es el error de interpretación más extendido. En la mayoría de los UNIX, la carga cuenta los procesos en estado R (ejecutándose o listos). En Linux, y solo en Linux, cuenta además los que están en estado D, es decir, en espera ininterrumpible de E/S (02-01).
La consecuencia práctica es enorme: en meteo-01, con 8 núcleos, una carga de 24 puede significar tres cosas completamente distintas —24 procesos peleando por la CPU, o 2 usando CPU y 22 esperando al disco, o cualquier mezcla— y la respuesta correcta es opuesta en cada caso. Añadir CPU al segundo escenario no arregla nada. Por eso la carga sirve para saber que algo pasa, nunca para saber qué.
uptime
# 03:12:44 up 41 days, load average: 24.31, 9.02, 4.11
mpstat -P ALL 1 3
# CPU %usr %nice %sys %iowait %irq %soft %steal %idle
# all 4,2 0,0 2,1 88,3 0,0 0,3 0,0 5,1
ps -eo state,pid,comm | awk '$1=="D"' | head # ¿quién está en espera ininterrumpible?Qué revela la combinación. Carga 24 con %iowait del 88 % y %usr del 4 % es concluyente: la CPU está prácticamente ociosa y los procesos se acumulan esperando al disco. El ps con filtro D nombra a los culpables. Si en cambio vieras %usr al 95 % y %iowait a 0, el problema sería genuinamente de cálculo.
top -b -n1 | head -5
# top - 03:12:44 up 41 days, 3 users, load average: 24,31, 9,02, 4,11
# Tareas: 214 total, 1 ejecutar, 186 hibernar, 27 parar, 0 zombie
# %Cpu(s): 4,2 us, 2,1 sy, 0,0 ni, 5,1 id, 88,3 wa, 0,0 hi, 0,3 si, 0,0 st
# MiB Mem : 16037,0 total, 412,0 free, 11204,0 used, 4421,0 buff/cache
# MiB Swap: 4095,0 total, 3967,0 free, 128,0 used. 4102,0 avail MemCómo leer la cabecera, que es donde está casi toda la información. La línea de tareas ya adelanta el diagnóstico: 27 procesos en estado "parar" —que en la traducción de top agrupa a los detenidos y a los ininterrumpibles— con solo uno ejecutándose es una anomalía enorme. htop presenta lo mismo de forma interactiva, con una barra por núcleo (útil para ver de un golpe si la carga está repartida), el árbol de procesos con F5 y la posibilidad de ordenar por cualquier columna; su ventaja real es que hace visible en un segundo lo que en top hay que buscar.
Los campos de la línea de CPU, uno a uno:
| Campo | Qué mide | Cuándo preocupa |
|---|---|---|
%us (user) |
Tiempo en código de usuario | Alto y sostenido: hay trabajo de cálculo real |
%sy (system) |
Tiempo en el núcleo | >20 % sostenido: exceso de llamadas al sistema, E/S mal bufferizada |
%ni (nice) |
Procesos con prioridad rebajada | Informativo |
%id (idle) |
Ocioso | — |
%wa (iowait) |
Ocioso, con E/S pendiente | Alto: el cuello de botella está en el almacenamiento |
%hi/%si |
Interrupciones hardware y software | %si alto: mucha red (02-07) |
%st (steal) |
CPU que el hipervisor dio a otro huésped | >2 %: vecino ruidoso o sobresuscripción (06-01) |
%wa merece un matiz que casi nadie explica: no es tiempo "gastado" en E/S, es tiempo ocioso habiendo E/S pendiente. Si la CPU tuviera otro trabajo que hacer, lo haría y el %wa bajaría sin que la E/S mejorase lo más mínimo. Por eso %wa bajo no descarta un problema de disco en una máquina ocupada: hay que mirar iostat.
%st es la métrica que solo existe en máquinas virtuales, y es la que explica un misterio recurrente: "mi proceso tarda el doble y la CPU está al 50 %". Si st es del 15 %, el hipervisor te está quitando uno de cada siete ciclos y no hay nada que puedas cambiar dentro del huésped.
pidstat -u 1 3 # CPU por proceso, por segundo
pidstat -t -p 1834 1 3 # desglose por HILO del proceso 1834
top -H -p 1834 # lo mismo, interactivo
taskset -pc 1834 # ¿está atado a unos núcleos concretos?Por qué el desglose por hilo importa. Un proceso al 100 % en una máquina de 8 núcleos puede ser un programa monohilo saturado —techo real, no hay más que rascar sin cambiar el código— o un proceso multihilo apenas ocupado. pidstat -t o top -H lo distinguen en dos segundos, y ese dato cambia por completo la recomendación.
Memoria: por qué free -h confunde a todo el mundo
free -m
# total usada libre compartido búf/caché disponible
# Mem: 16037 11204 412 890 4421 4102
# Swap: 4095 128 3967Casi todo el mundo lee "libre: 412 MB" y entra en pánico. Es la lectura equivocada. Linux usa toda la RAM que sobra como caché de páginas (02-03), porque memoria libre es memoria desperdiciada: guardando ahí los ficheros leídos recientemente, evita ir al disco. Esa caché es reclamable al instante: si un proceso pide memoria, el núcleo descarta páginas limpias de caché y se la da.
La columna que importa es disponible (MemAvailable), que es la estimación del núcleo de cuánta memoria puede conseguir un proceso nuevo sin provocar intercambio. Aquí, 4.102 MB: la máquina está cómoda pese al "412 libre".
| Concepto | Significado | ¿Reclamable? |
|---|---|---|
usada |
Anónima de procesos, más núcleo | No |
búf/caché |
Caché de páginas y de inodos | Sí, casi toda |
libre |
Nunca usada | Sí (y es normal que sea baja) |
disponible |
Lo que puede conseguir un proceso nuevo | Es la cifra buena |
grep -E 'MemTotal|MemFree|MemAvailable|Cached|Dirty|Writeback|SwapCached' /proc/meminfo
vmstat 1 5
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 2 14 131072 421884 8912 4523112 0 2048 8192 12288 4102 8934 4 3 5 88 0Cómo leer el intercambio. swpd (cuánto hay en swap) puede ser alto sin que pase nada: son páginas que se expulsaron hace días y nadie ha vuelto a pedir. Lo que indica un problema activo son si y so, las páginas que entran y salen por segundo. Un so sostenido de 2.048 páginas/s son 8 MB/s de escritura en swap; si además hay si alto a la vez, el sistema está en thrashing (02-04): dedica más tiempo a mover páginas que a trabajar, y la latencia se dispara por dos órdenes de magnitud.
Detección de fugas de memoria. Una fuga no se ve en una foto: se ve en una película. Sigue el RSS —memoria física realmente ocupada, frente al VSZ que es solo espacio de direcciones reservado (02-04)— a lo largo del tiempo:
while true; do
printf '%s %s\n' "$(date -Is)" "$(awk '/VmRSS/{print $2}' /proc/1834/status)"
sleep 60
done >> /var/log/meteora/rss-meteo-api.logCómo interpretarlo. Un servicio sano estabiliza su RSS tras el calentamiento; una fuga dibuja una recta ascendente que no se dobla nunca. Si el RSS de meteo-api sube 40 MB cada hora de forma constante, en 50 horas alcanzará el MemoryMax=2G de su unidad y systemd lo matará. La ventaja de haber puesto ese límite en 07-02 es que la fuga mata solo al servicio culpable en lugar de dejar que el OOM killer del sistema elija víctima.
El rastro del OOM killer, que hay que saber reconocer de memoria:
dmesg -T | grep -iE 'out of memory|killed process'
# [Mon Aug 31 03:07:52 2026] Out of memory: Killed process 1834 (meteo-api)
# total-vm:3982104kB, anon-rss:2914208kB, file-rss:0kB, shmem-rss:8192kB, UID:990 pgtables:6284kB oom_score_adj:0
journalctl -k --since '-1 hour' | grep -i oomQué te dice esa línea. Nombra al proceso elegido, su UID (990, o sea meteora) y su anon-rss en el momento de morir: 2,9 GB. Recuerda de 02-04 que el OOM killer elige por oom_score, que es principalmente proporcional a la memoria usada, así que suele matar al proceso más grande, no al culpable. Un síntoma típico y desconcertante es que muere la base de datos porque un script chapucero pidió toda la RAM.
E/S: iostat -x campo a campo
iostat -x 1 3
# Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s r_await w_await aqu-sz rareq-sz %util
# md0 3891,0 42,0 15564,0 672,0 0,0 0,0 41,20 2,10 18,24 4,00 99,80
# sda 1948,0 21,0 7792,0 336,0 0,0 0,0 40,85 2,05 9,12 4,00 99,60
# sdb 1943,0 21,0 7772,0 336,0 0,0 0,0 41,55 2,08 9,11 4,00 99,70| Campo | Qué es | Qué mirar |
|---|---|---|
r/s, w/s |
Operaciones por segundo (IOPS) | Compáralo con la capacidad del dispositivo |
rkB/s, wkB/s |
Ancho de banda | Junto con IOPS da el tamaño medio de petición |
rrqm/s, wrqm/s |
Peticiones fusionadas por el planificador | Alto = acceso secuencial que el núcleo agrupa |
r_await, w_await |
Latencia media total (cola + servicio), en ms | La métrica de dolor: >20 ms en lectura ya se nota |
aqu-sz |
Longitud media de la cola | La saturación de USE |
rareq-sz |
Tamaño medio de petición de lectura, en KB | 4 KB = aleatorio; 128-512 KB = secuencial |
%util |
Fracción de tiempo con al menos una petición en vuelo | Ojo: engaña en NVMe |
Diagnóstico del ejemplo. rareq-sz de 4,00 KB con rrqm/s a cero dice que son lecturas aleatorias de un bloque: no hay nada que fusionar porque los bloques no son contiguos. 3.891 lecturas/s de 4 KB son solo 15,5 MB/s de ancho de banda —irrisorio— pero casi 4.000 IOPS, que para un RAID 1 de discos mecánicos (unas 150-200 IOPS por disco) es un orden de magnitud por encima de su capacidad. De ahí el aqu-sz de 18 (dieciocho peticiones esperando de media) y el r_await de 41 ms. La causa no es "el disco es lento": es el patrón de acceso, exactamente lo que se explicó en 02-05.
Por qué %util engaña en NVMe. El campo se calcula como el porcentaje de tiempo en que había al menos una petición en vuelo. En un disco mecánico, con un único cabezal, eso equivale de verdad a "ocupado". Un NVMe moderno atiende decenas de miles de IOPS en paralelo repartidas en múltiples colas: puede estar al 100 % de %util usando el 5 % de su capacidad real. En SSD y NVMe, las métricas fiables son await y aqu-sz, no %util.
pidstat -d 1 3 # E/S por proceso: kB_rd/s, kB_wr/s, iodelay
iotop -oPa # interactivo, solo procesos con E/S activa
cat /proc/1834/io # contadores acumulados del proceso
filefrag -v /var/lib/meteora/lecturas/2026-08-31.dat | tail -3 # fragmentación en extentsPara qué sirve cada uno. pidstat -d atribuye la E/S a procesos concretos, que es el paso que convierte "el disco está saturado" en "el agregador está saturando el disco"; su columna iodelay mide el tiempo que el proceso ha pasado bloqueado esperando. filefrag cuenta los extents de un fichero (04-05): si un fichero de 17 MB está en 3 extents, leerlo entero es prácticamente secuencial; si está en 4.000, hasta una lectura completa se comporta como acceso aleatorio.
Cómo se ve la saturación del RAID 1 de Meteora. Fíjate en que en la salida de arriba md0 recibe 3.891 lecturas/s y cada disco físico atiende unas 1.945: el RAID 1 reparte las lecturas entre las dos copias, lo que duplica los IOPS de lectura disponibles, pero no ayuda nada en escritura, porque cada escritura debe ir a ambos discos. Es la asimetría fundamental del espejo, y explica por qué un RAID 1 sirve para dar disponibilidad y algo de lectura, pero jamás resuelve un problema de escrituras.
Red: colas, retransmisiones y latencia
ss -s
# Total: 1284
# TCP: 1201 (estab 940, closed 187, orphaned 0, timewait 186)
ss -tanp state listen '( sport = :443 )'
# Recv-Q Send-Q Local Address:Port Process
# 129 2048 0.0.0.0:443 users:(("meteo-api",pid=1834,fd=7))
ip -s link show eth0 | sed -n '3,6p'
nstat -az | grep -E 'TcpRetransSegs|TcpExtListenOverflows|TcpExtListenDrops'# ip -s link show eth0 # RX: bytes packets errors dropped overrun mcast # 8912443021 9124883 0 1204 0 41 # TX: bytes packets errors dropped carrier collsns # 4412009834 6021144 0 0 0 0
Qué significa cada cosa, y aquí hay una sutileza que confunde a mucha gente. En un socket en escucha, las columnas cambian de sentido: Recv-Q es el número de conexiones ya establecidas esperando a que la aplicación haga accept() y Send-Q es el tamaño máximo de esa cola (el Backlog=2048 de la unidad de 07-02). Un Recv-Q de 129 sostenido significa que meteo-api no acepta conexiones tan rápido como llegan: el problema no es la red, es que la aplicación está ocupada o bloqueada. Si la cola se llena del todo, el núcleo empieza a descartar SYN y el contador ListenOverflows crece; el cliente ve una conexión que no responde y reintenta, amplificando el problema.
Las retransmisiones (TcpRetransSegs) indican pérdida de paquetes: un porcentaje sostenido por encima del 0,1 % del total de segmentos apunta a congestión o a un enlace defectuoso. Y en ip -s link, las columnas errors y dropped de recepción distinguen un fallo físico (cable, negociación de velocidad) de un descarte por cola llena en el propio núcleo.
Latencia frente a ancho de banda, distinción que decide muchos diseños: el ancho de banda es cuántos bytes por segundo caben; la latencia es cuánto tarda el primero en llegar. Un enlace de 10 Gb/s con 200 ms de ida y vuelta es magnífico para transferir un fichero de 50 GB y pésimo para una API que hace 30 consultas encadenadas, porque esas 30 idas y vueltas son 6 segundos irreducibles: ninguna mejora de ancho de banda los baja. Cuando meteo-api responde lento, la pregunta correcta es si tarda en empezar a responder (latencia, dependencias, bloqueos) o en terminar (volumen, ancho de banda).
Presión de recursos: PSI
PSI (Pressure Stall Information, Linux 4.20+) es probablemente la métrica más útil aparecida en la última década, y responde justo a la pregunta que las demás esquivan: cuánto tiempo se está perdiendo por culpa de cada recurso.
cat /proc/pressure/io
# some avg10=87.42 avg60=71.03 avg300=44.18 total=1904821334
# full avg10=61.19 avg60=48.77 avg300=29.02 total=1233908112
cat /proc/pressure/cpu /proc/pressure/memoryCómo se lee. some es el porcentaje de tiempo en que al menos una tarea estuvo bloqueada esperando ese recurso; full es el porcentaje en que todas las tareas ejecutables lo estaban, es decir, tiempo en que la máquina entera no progresó. Los tres números son medias móviles de 10, 60 y 300 segundos, lo que da tendencia sin necesidad de muestrear.
Un io full avg10 del 61 % significa, literalmente, que en los últimos 10 segundos la máquina ha pasado seis de cada diez segundos sin poder hacer nada por esperar al disco. Compáralo con lo que dirían las métricas clásicas del mismo momento: la CPU parece ociosa (%id alto), la memoria parece bien y solo el %wa insinúa algo. PSI lo dice sin ambigüedad y, sobre todo, en unidades de impacto —tiempo perdido— en vez de en unidades de recurso. Por eso es una excelente base para alertar: io full avg60 > 20 % es un umbral que significa lo mismo en cualquier máquina, con cualquier disco.
PSI también existe por cgroup (/sys/fs/cgroup/system.slice/meteo-api.service/io.pressure), lo que permite responder a "¿qué servicio está sufriendo?" y "¿qué servicio está causando el sufrimiento?" por separado.
Observación profunda y su coste: strace, perf, eBPF
Cuando las métricas agregadas no bastan, se baja al detalle. Estas herramientas responden a "¿qué está haciendo exactamente este proceso?", pero cuestan, y hay que saber cuánto.
strace -c -p 1834 -f # resumen: cuántas llamadas y cuánto tiempo en cada una
strace -T -e trace=read,pread64 -p 1834 2>&1 | head -20 # con duración por llamadaAdvertencia seria. strace funciona con ptrace, que detiene el proceso en cada entrada y salida de llamada al sistema y hace dos cambios de contexto extra por cada una. La ralentización típica va de 10 a 100 veces para un proceso intensivo en llamadas. Sobre meteo-api en producción, con miles de peticiones por segundo, strace no es una observación: es una caída provocada. Úsalo con -c (que solo agrega), durante pocos segundos, sobre un proceso poco crítico, o en un entorno de pruebas. La regla es: strace para entender un programa, nunca para medir uno en producción.
perf top -p 1834 # qué funciones consumen CPU, en vivo
perf record -F 99 -g -p 1834 -- sleep 30 # muestreo a 99 Hz con pila de llamadas
perf report --stdio | head -30Por qué perf sí es viable. No intercepta nada: muestrea. A 99 Hz toma 99 fotos por segundo de dónde está el contador de programa y qué pila hay debajo; el sobrecoste típico está por debajo del 1-2 %. La frecuencia 99 y no 100 es un truco deliberado para no sincronizarse con temporizadores del sistema que suelen ir a 100 Hz y sesgarían el muestreo. El resultado natural de perf record es un gráfico de llamas (flame graph): un dibujo en el que el eje horizontal es la proporción de muestras —no el tiempo— y el vertical la profundidad de la pila, de modo que las mesetas anchas señalan al instante dónde se va la CPU. Es la forma más rápida que existe de encontrar un punto caliente de código.
# eBPF: instrumentación segura en el núcleo, con sobrecoste mínimo
bpftrace -e 'tracepoint:syscalls:sys_enter_openat { @[comm] = count(); }'
bpftrace -e 'tracepoint:block:block_rq_issue { @bytes = hist(args->bytes); }'
biolatency-bpfcc 10 1 # histograma de latencia de bloqueQué aporta eBPF. Programas verificados que el núcleo ejecuta en puntos de instrumentación, agregando dentro del núcleo y devolviendo solo el resultado, sin copiar cada evento a espacio de usuario. El primer ejemplo cuenta las openat por programa; el segundo dibuja un histograma del tamaño de las peticiones de bloque, que en el caso de Meteora mostraría de un vistazo el pico en 4 KB que delata el acceso aleatorio; biolatency da la distribución de latencias de disco, con la que se ven las colas largas que una media esconde. Es la evolución natural de todo lo anterior: la potencia de strace con un coste más cercano al de perf.
Los registros como fuente de diagnóstico
Las métricas dicen qué ocurre; los registros suelen decir por qué. Con las herramientas de 05-04:
journalctl --since '03:00' --until '03:20' -p warning --no-pager # todo el sistema, acotado
journalctl -u meteo-api.service --since '03:00' -o short-precise # con microsegundos
journalctl -k --since '03:00' | grep -iE 'oom|error|reset|degraded'
awk '$9 >= 500 {c[$9]++} END {for (k in c) print c[k], k}' /var/log/meteora/meteo-api.logLa técnica que más rinde es la correlación temporal. Toma el instante exacto en que empezó el síntoma (03:05, según el percentil que calculaste al principio) y mira todo lo que pasó en la máquina en esa ventana, sin filtrar por servicio: un despliegue, una tarea programada que arrancó, un logrotate, un disco que reportó un error, un pico de conexiones. La causa suele estar en esa ventana, y muchas veces en un servicio distinto del que da el síntoma. Un hueco sospechoso en los registros —minutos sin ninguna entrada en un fichero que escribe cada segundo— es en sí mismo un hallazgo de primer orden.
# ¿Hay huecos en un registro que debería escribirse cada segundo?
awk '{split($4, t, ":"); m = t[2]":"t[3]; if (m != prev) {print m; prev = m}}' \
/var/log/meteora/meteo-api.log | uniq -c | awk '$1 < 10'Qué hace. Cuenta cuántas entradas hay por minuto y muestra los minutos con menos de diez. En un servicio que registra miles de peticiones por minuto, un minuto con dos entradas —o ausente— significa que el servicio estuvo bloqueado, que el disco no aceptaba escrituras… o que alguien manipuló el fichero, posibilidad que hay que tomarse en serio y que veremos en 07-04.
De la observación puntual a la monitorización continua
Todo lo anterior sirve cuando ya hay un incidente y tú estás delante. Eso no escala: hace falta que los números se recojan siempre, para poder mirar hacia atrás y para que alguien avise sin que nadie esté mirando.
| Pieza | Qué hace | Ejemplos |
|---|---|---|
| Exportador | Expone métricas de la máquina o del servicio | node_exporter, métricas propias de meteo-api |
| Base de series temporales | Muestrea y almacena (métrica, etiquetas, tiempo, valor) | Prometheus, VictoriaMetrics, InfluxDB |
| Paneles | Representan la evolución y facilitan la correlación | Grafana |
| Alertas | Evalúan reglas y notifican | Alertmanager |
| Registros y trazas | Contexto y seguimiento de peticiones | Loki, OpenTelemetry |
# Un exportador es, en el fondo, un servidor HTTP que devuelve texto plano
curl -s localhost:9100/metrics | grep -E '^node_(load1|memory_MemAvailable_bytes|pressure)'
# node_load1 24.31
# node_memory_MemAvailable_bytes 4.30178304e+09
# node_pressure_io_waiting_seconds_total 1904.821334Qué demuestra. No hay magia: el exportador lee /proc/loadavg, /proc/meminfo y /proc/pressure/io —los mismos ficheros que has estado consultando a mano— y los publica en un formato que una base de series temporales recoge cada 15 segundos. Entender esto tiene una consecuencia práctica: cualquier número que sepas obtener con un comando lo puedes convertir en una métrica histórica y en una alerta, incluida la salida del script de verificación de 07-01.
Cuatro decisiones prácticas que determinan si el sistema sirve o estorba:
- Intervalo de muestreo. Con 60 segundos no verás un pico de 20; con 5 segundos multiplicas por doce el volumen. Para infraestructura, 15 segundos es el punto de equilibrio habitual.
- Cardinalidad. Cada combinación distinta de etiquetas es una serie temporal. Etiquetar por
estacion_idcon 3.000 estaciones y 20 métricas son 60.000 series por instancia: es la forma más común de tumbar un sistema de monitorización. Etiqueta por dimensiones de cardinalidad acotada (servicio, endpoint, código de estado), nunca por identificadores libres. - Retención y resolución. Alta resolución poco tiempo (15 s durante 15 días) y agregados a largo plazo (5 min durante 2 años, para tendencias y capacidad).
- Percentiles, no medias. Si el 99 % de las peticiones tarda 20 ms y el 1 % tarda 10 s, la media es 120 ms y no describe la experiencia de nadie. El p99 es el número que corresponde a los usuarios que se quejan. Guarda p50, p95 y p99, y recuerda que los percentiles no se promedian: la media de los p99 de diez máquinas no es el p99 del conjunto.
Alertas útiles, SLI y SLO
La diferencia entre un sistema de alertas y una fuente de ruido cabe en una frase: alerta sobre síntomas que percibe el usuario, no sobre utilización de recursos.
| Mala alerta | Por qué falla | Buena alerta |
|---|---|---|
| "CPU > 80 %" | Una máquina bien aprovechada está al 80 %; y puede ir mal al 30 % | "p99 de latencia > 1 s durante 10 min" |
| "Disco al 85 %" | Dispara siempre y se ignora | "El disco se llenará en < 4 h según la tendencia" |
| "Proceso caído" | systemd ya lo reinicia | "El servicio lleva 5 min sin arrancar (start-limit-hit)" |
| "Hay swap usada" | Puede llevar semanas ahí sin efecto | "si/so > 0 durante 5 min" o "memory full avg60 > 10 %" |
Una alerta debe cumplir tres condiciones: es real (algo va mal de verdad), es accionable (hay algo que quien la recibe puede hacer) y es urgente (no puede esperar a mañana). Si falla alguna, no es una alerta: es un panel, o un tíquet.
Formalizar esto son los SLI y los SLO. Un SLI (indicador) es una medida de la experiencia del usuario: "porcentaje de peticiones a /v1/lecturas respondidas correctamente en menos de 500 ms". Un SLO (objetivo) es el nivel comprometido: "99,5 % en una ventana de 30 días". La consecuencia práctica es el presupuesto de error: 0,5 % de 30 días son unas 3,6 horas de incumplimiento permitidas al mes. Ese presupuesto convierte discusiones de opinión en decisiones con datos —si queda mucho presupuesto, se despliega y se experimenta; si se ha consumido, se congela y se estabiliza— y define la alerta que de verdad importa: avisar cuando el presupuesto se está agotando demasiado rápido, no cuando un recurso pasa de un umbral arbitrario.
Planificación de capacidad
Diagnosticar es reaccionar; planificar capacidad es no tener que reaccionar. Con las series a largo plazo se responden preguntas como cuándo se llenará /var/lib/meteora, cuántas estaciones más aguanta el ingestor o si el RAID 1 dará abasto el próximo verano.
Un ejemplo con los números de Meteora. Cada día genera un fichero de 17.280.000 bytes, es decir 16,5 MiB; al año, unos 6,0 GiB. Si el volumen tiene 200 GB y ya hay 120 GB usados, quedan 80 GB, que a ese ritmo son más de trece años: el crecimiento por número de días es irrelevante. Pero si el negocio prevé pasar de 500 a 3.000 estaciones, el volumen diario se multiplica por seis (99 MiB/día, 35 GiB/año) y el margen baja a poco más de dos años… y, mucho antes que el espacio, el problema será el IOPS: seis veces más lecturas concurrentes sobre un RAID 1 que ya vimos saturado a 4.000 IOPS aleatorias.
De ahí las dos reglas de la planificación de capacidad: proyecta sobre el impulsor del negocio (estaciones, usuarios, peticiones), no sobre el calendario; y recuerda que los recursos no se agotan a la vez —normalmente el cuello de botella llega por IOPS o por latencia mucho antes que por espacio o por CPU—. Y ten presente que la latencia no crece de forma lineal: por teoría de colas, cuando la utilización pasa del 70-80 %, el tiempo de espera se dispara, así que planificar para el 95 % de utilización es planificar un incidente.
Laboratorio guiado: provocar y observar cada saturación
Advertencia expresa: haz esto en una máquina virtual de pruebas desechable, nunca en producción. Cada ejercicio provoca deliberadamente una degradación; alguno puede dejar la máquina sin responder unos minutos. Ten a mano cómo reiniciarla.
Laboratorio 1 — Saturación de CPU. En una terminal, stress-ng --cpu 8 --timeout 120s. En otra, observa:
Qué debes ver y por qué. La carga sube hacia el número de trabajadores; %usr cerca del 100 % y %iowait en cero; la columna r de vmstat (procesos listos) crece por encima del número de núcleos; y cpu some avg10 sube claramente mientras full se mantiene bajo, porque siempre hay alguien ejecutándose. Contrasta esto con la firma de la E/S: carga alta con %usr alto es CPU; carga alta con %wa alto es disco. Esa comparación es el objetivo del ejercicio.
Laboratorio 2 — Presión de memoria e intercambio. stress-ng --vm 2 --vm-bytes 80% --timeout 120s:
Qué debes ver. disponible cae; si/so empiezan a moverse cuando la memoria anónima supera lo que cabe; memory some sube antes que ningún otro indicador. Si aprietas más (--vm-bytes 95%), llegará el OOM killer y verás en dmesg la línea Killed process con su anon-rss, que es exactamente el rastro que aprendiste a reconocer. Observa también cómo la caché (búf/caché) se reduce automáticamente para ceder memoria: la demostración práctica de que no era memoria ocupada.
Laboratorio 3 — Saturación de E/S aleatoria (la firma del caso de Meteora):
fio --name=aleatorio --rw=randread --bs=4k --size=2G --numjobs=4 \
--iodepth=32 --runtime=120 --time_based --directory=/var/tmp
# En otra terminal:
iostat -xz 1 ; pidstat -d 1 ; cat /proc/pressure/io ; iotop -oPaQué debes ver y comparar. rareq-sz clavado en 4 KB, rrqm/s casi cero (nada que fusionar), aqu-sz alto, await de decenas de milisegundos y %util cerca del 100 %. Ahora repite con --rw=read --bs=1M: verás un ancho de banda muchísimo mayor, rareq-sz grande, rrqm/s alto y await bajo, con la misma %util. Esa comparación es la lección central del laboratorio y del módulo entero: %util no distingue un disco cómodo de uno ahogado, y el patrón de acceso importa más que el dispositivo. Con --direct=1 evitas además que la caché de páginas te enmascare los resultados.
Termina cada laboratorio anotando la "firma" de cada saturación: qué combinación exacta de números viste. Ese cuaderno es lo que te permitirá reconocer el problema en tres segundos cuando ocurra de verdad.
Errores Comunes y Consejos
| Error | Por qué es un error | Qué hacer |
|---|---|---|
| Interpretar la carga media como uso de CPU | En Linux incluye los procesos en estado D |
Cruza con %wa, %usr y ps -eo state |
Alarmarse por free bajo |
La caché es reclamable | Mira disponible / MemAvailable |
Fiarse de %util en SSD/NVMe |
El dispositivo atiende en paralelo | Usa await y aqu-sz |
Usar el primer registro de vmstat/iostat |
Es la media desde el arranque | Descarta la primera muestra |
strace en producción |
Ralentización de 10× a 100× | perf, eBPF, o strace -c unos segundos |
| Medir con medias | Ocultan la cola que sufren los usuarios | p50, p95, p99 |
| Alertar sobre utilización | Genera ruido y se acaba ignorando | Alerta sobre síntomas del usuario |
| Cambiar varias cosas a la vez | No sabrás qué funcionó | Una hipótesis, una comprobación |
| Diagnosticar sin línea base | No sabes qué es anormal | Guarda una foto periódica |
| Etiquetar métricas por identificador libre | Explosión de cardinalidad | Etiquetas de cardinalidad acotada |
| Mirar solo el servicio que da el síntoma | La causa suele estar en otro | Correlaciona toda la ventana temporal |
Consejos: empieza siempre por dmesg, porque un solo mensaje puede ahorrarte una hora; aprende de memoria la lista de los 60 segundos y ejecútala entera aunque creas saber la respuesta, porque descartar tiene valor; mide antes y después de cada mitigación, con el mismo comando; y guarda las salidas en un fichero con marca de tiempo (comando | tee -a /var/tmp/incidente-$(date +%s).log), porque en el post mortem esas capturas son irrepetibles.
Ejercicios
Ejercicio 1: leer una foto del sistema
Ante una queja de lentitud en meteo-api obtienes esto:
load average: 31.44, 12.07, 5.90 %usr 3,1 %sys 2,4 %iowait 91,2 %steal 0,0 %idle 3,3 free -m: total 16037 usada 9210 libre 388 búf/caché 6439 disponible 6120 vmstat: r=1 b=27 si=0 so=0 bi=61440 bo=1024 cs=3980 iostat md0: r/s=4102 w/s=38 rareq-sz=4,00 rrqm/s=0,0 await=52,10 aqu-sz=27,40 %util=99,9 /proc/pressure/io: full avg10=74.28
Di qué recurso es el cuello de botella, qué descartas con cada línea y cuál sería tu siguiente comando.
Ejercicio 2: distinguir dos incidentes de memoria
Dos máquinas se comportan así. Determina en cuál hay un problema real y qué harías en cada caso.
- A:
libre=210 MB,disponible=5.980 MB,swpd=2.100 MB,si=0,so=0,memory some avg60=0.4 - B:
libre=1.900 MB,disponible=1.980 MB,swpd=180 MB,si=1.840,so=2.310,memory some avg60=63.7
Ejercicio 3: convertir alertas de ruido en alertas útiles
Reescribe estas tres alertas para que cumplan las condiciones de real, accionable y urgente, y justifica cada cambio: (a) "CPU del servidor > 85 % durante 1 minuto"; (b) "Hay memoria de intercambio en uso"; (c) "El proceso meteo-api no está en ejecución".
Soluciones
Solución 1
Cuello de botella: E/S de disco, con un patrón de lectura aleatoria de 4 KB. Descartes línea a línea:
- Carga 31 con
%usr3,1 % y%idle3,3 %: descarta la CPU como causa. Con 8 núcleos, una carga de 31 y casi nada de tiempo de usuario solo puede explicarse por procesos en estadoD, que en Linux cuentan en la carga. %iowait91,2 % y%steal0: confirma espera de E/S y descarta que sea un problema del hipervisor.disponible6.120 MB,si/soa cero: descarta la memoria. Ellibrebajo es normal por la caché.vmstatconr=1yb=27: la prueba definitiva. Solo un proceso listo para ejecutar y veintisiete bloqueados en E/S ininterrumpible. Es la firma exacta de la saturación de disco.rareq-sz=4,00 conrrqm/s=0: lecturas aleatorias de 4 KB; el planificador no puede fusionar nada porque los bloques no son contiguos. 4.102 IOPS es un orden de magnitud por encima de lo que da un RAID 1 mecánico.aqu-sz=27,4 yawait=52 ms: saturación severa, no simple utilización alta. El disco está al 99,9 % y con 27 peticiones esperando.io full avg10=74,28: en los últimos 10 segundos, la máquina no ha progresado durante casi tres cuartas partes del tiempo por esperar al disco.
Siguiente comando: pidstat -d 1 5 (o iotop -oPa), para atribuir esa E/S a un proceso concreto. Después, filefrag sobre los ficheros implicados y cat /proc/<pid>/io, para entender si el patrón aleatorio viene del acceso del programa o de la fragmentación del fichero.
Solución 2
A: no hay problema. disponible de casi 6 GB indica margen sobrado; el libre bajo es el comportamiento normal de la caché de páginas. Los 2.100 MB en swap son histórico: páginas expulsadas hace tiempo que nadie ha vuelto a necesitar. Lo demuestran si=0 y so=0 —no hay tráfico de intercambio ahora— y una presión de memoria del 0,4 %, es decir, ruido. Acción: ninguna, salvo anotar el valor en la línea base. Vaciar la swap "por estética" con swapoff -a && swapon -a es contraproducente: fuerza a traer a RAM páginas que nadie usa.
B: problema real y grave. disponible de solo 1.980 MB, y sobre todo si=1.840 y so=2.310 páginas por segundo, o sea del orden de 7 y 9 MB/s entrando y saliendo simultáneamente: eso es thrashing, el sistema mueve páginas en ambos sentidos porque el conjunto de trabajo no cabe en RAM. La presión del 63,7 % confirma que se está perdiendo casi dos tercios del tiempo. Acciones, en orden: identificar al consumidor con ps -eo pid,rss,comm --sort=-rss | head; comprobar en dmesg si el OOM killer ya ha actuado; mirar la evolución del RSS para distinguir una fuga de una carga legítima; como mitigación inmediata, aplicar o ajustar MemoryMax en la unidad del servicio culpable (07-02) para acotar el daño; y como solución de fondo, corregir la fuga o dimensionar la máquina. Bajar vm.swappiness no arregla nada aquí: el problema no es que se use swap, es que no hay memoria suficiente.
Solución 3
(a) "CPU > 85 % durante 1 minuto" → "El p99 de latencia de /v1/lecturas supera 1 s durante 10 minutos". El problema de la original es que mide un recurso, no un daño: una máquina bien dimensionada debe estar alta de CPU, y un servicio puede ir fatal con la CPU al 20 % si el cuello está en el disco. Además, un minuto es demasiado corto y dispara con cualquier pico legítimo, como el arranque del agregador. La versión nueva mide lo que sufre el usuario y su ventana de 10 minutos filtra los transitorios. Como alerta secundaria y de menor prioridad, cpu some avg300 > 40 % sí es defendible, porque mide tiempo perdido y no utilización.
(b) "Hay memoria de intercambio en uso" → "si+so > 0 de forma sostenida durante 5 minutos", o mejor "memory full avg60 > 10 %". Que haya páginas en swap no significa nada, como demuestra la máquina A del ejercicio anterior: la alerta original dispararía en máquinas perfectamente sanas y acabaría silenciada. Lo que duele es el tráfico de intercambio, o directamente el tiempo perdido que mide PSI, que además es comparable entre máquinas distintas.
(c) "El proceso meteo-api no está en ejecución" → "meteo-api.service lleva 5 minutos sin alcanzar el estado activo (o ha entrado en failed)". La original es ruido garantizado: cada reinicio legítimo, cada despliegue y cada Restart=on-failure que funciona como debe generarían una alerta a las tres de la madrugada por algo que el sistema ya ha resuelto solo. La nueva solo dispara cuando la recuperación automática ha fallado, que es el único caso en que hace falta un humano. Es exactamente el estado estable que conseguíamos con StartLimitBurst en 07-02, y systemctl list-units --failed es la comprobación que la implementa.
Conclusión
El mensaje central de esta lección es que el método vale más que las herramientas. Sabes distinguir un síntoma de una causa, cuantificar antes de tocar, cambiar una cosa cada vez y apoyarte en una línea base; y tienes dos marcos con nombre: USE para recorrer los recursos con utilización, saturación y errores —recordando que la saturación es la métrica que no tiene techo y que casi nadie mira—, y RED para medir el servicio desde fuera con peticiones, errores y duración.
Sobre eso has aprendido a leer los números de verdad, que casi siempre significan algo distinto de lo que parecen. La carga media incluye los procesos en estado D y por eso no es utilización de CPU. %wa es tiempo ocioso con E/S pendiente, así que un valor bajo no descarta un problema de disco. free confunde porque la caché no es memoria ocupada y la cifra buena es disponible; el intercambio duele cuando hay si/so, no cuando hay swpd. %util engaña en NVMe y las métricas fiables son await y aqu-sz. En un socket de escucha, Recv-Q son conexiones esperando accept() y delata a la aplicación, no a la red. Y PSI mide directamente el tiempo perdido, en unidades comparables entre máquinas, que es lo que convierte una alerta en algo con sentido.
Has visto también el coste de observar: strace ralentiza entre 10 y 100 veces porque intercepta, mientras que perf muestrea a 99 Hz con un 1-2 % y eBPF agrega dentro del núcleo; y has subido de la máquina a la flota, con exportadores, series temporales, cardinalidad, percentiles, alertas basadas en síntomas y presupuestos de error derivados de un SLO. En el laboratorio has provocado las tres saturaciones y anotado su firma, incluida la comparación que resume el módulo: lectura aleatoria de 4 KB y lectura secuencial de 1 MB dan el mismo %util y experiencias de usuario incomparables.
Ya tienes las tres piezas: la interfaz para actuar (07-01), el control de lo que corre y cuándo (07-02) y el método para saber qué pasa. Falta juntarlo todo bajo presión, con datos incompletos, a una hora mala y con la incertidumbre real de no saber de antemano cuál es la respuesta.
Es la última lección del curso: Caso Práctico Final: Diagnosticar un Servidor en Producción. Son las 03:12 y acaba de llegar un aviso.
Fundamentos de Sistemas Operativos
Módulo 1: Introducción a los Sistemas Operativos
- Conceptos Básicos de Sistemas Operativos
- Historia y Evolución de los Sistemas Operativos
- Tipos de Sistemas Operativos
- Funciones Principales de un Sistema Operativo
- Arquitectura del Núcleo: Monolítico, Microkernel e Híbrido
- Modo Usuario, Modo Núcleo y Llamadas al Sistema
Módulo 2: Gestión de Recursos
- Gestión de Procesos
- Planificación de la CPU
- Gestión de Memoria
- Memoria Virtual y Paginación
- Gestión de Almacenamiento
- Gestión de Dispositivos
- Controladores, Interrupciones y Operaciones de E/S
Módulo 3: Concurrencia
- Conceptos de Concurrencia
- Hilos y Procesos
- Comunicación entre Procesos (IPC)
- Sincronización y Exclusión Mutua
- Problemas Clásicos de Concurrencia
- Interbloqueos: Prevención, Detección y Recuperación
Módulo 4: Estructuras de Archivos
- Sistemas de Archivos
- Estructuras de Directorios
- Particiones, Montaje y Sistema de Archivos Virtual
- Gestión de Archivos
- Asignación de Espacio, Journaling e Integridad
- Seguridad y Permisos de Archivos
Módulo 5: Protección y Seguridad del Sistema
- Principios de Protección y Control de Acceso
- Usuarios, Autenticación y Escalada de Privilegios
- Amenazas Comunes y Endurecimiento del Sistema
- Auditoría, Registros y Respuesta a Incidentes
Módulo 6: Virtualización y Contenedores
- Virtualización: Hipervisores y Máquinas Virtuales
- Contenedores: Namespaces y cgroups
- El Sistema Operativo en la Nube
- Sistemas Operativos Móviles y de Tiempo Real
