Tutorial de PREEMPT_RT en Linux: instalación, pruebas y tuning

  • PREEMPT_RT reduce latencias y ya puede configurarse en el kernel principal para x86, ARM64 y RISC-V.
  • Instala binarios RT (p. ej., Debian) o compila con scripts, desactivando opciones de depuración que elevan el jitter.
  • Valida con cyclictest/rtla y ajusta IRQs, prioridades y aislamiento de CPU para cargas crĆ­ticas.
  • Soporta escenarios avanzados: drivers NVIDIA en RT y RTVM con ACRN y passthrough dedicado.

PREEMPT_RT Linux tutorial imagen principal

Si trabajas con sistemas donde el tiempo de respuesta lo es todo, PREEMPT_RT es el ingrediente que convierte un Linux «normal» en un sistema apto para tiempo real. Hablamos de latencias controladas, planificadores con prioridad estricta y herramientas de anÔlisis que permiten afinar hasta el último microsegundo. En este tutorial-dossier encontrarÔs, bien ordenado, qué es PREEMPT_RT, su estado en el kernel, cómo instalarlo o compilarlo, cómo medir y optimizar, y hasta cómo montarlo en una VM de tiempo real con ACRN.

AdemÔs de la teoría, te traigo instrucciones prÔcticas respaldadas por scripts que automatizan la compilación de kernels RT, paquetes listos para usar en distribuciones populares y recetas Yocto. VerÔs también cómo verificar que el sistema corre en modo RT, qué opciones del kernel conviene desactivar para evitar picos de latencia y cómo afinar IRQs, CPU y servicios. Incluso tocamos la compatibilidad con controladores NVIDIA en entornos PREEMPT_RT y un caso real con Clear Linux en un Intel NUC preparado para tareas críticas.

QuƩ es PREEMPT_RT y en quƩ punto estƔ en el kernel

PREEMPT_RT nace como una serie de parches que transforman Linux en un sistema con comportamiento de tiempo real, con el objetivo de reducir latencias y garantizar previsibilidad. El proyecto arrancó en 2005 bajo el paraguas Realtime-Preempt (-rt), pasó a la Fundación Linux en 2015 y ha sido clave para sectores como finanzas, audio/vídeo profesional, aviación, medicina, robótica, telecom y automatización industrial.

Desde 2019 se ha ido promoviendo su código hacia el kernel principal. Con la serie 6.12 se habilita la configuración de tiempo real en el kernel principal para x86, ARM64 y RISC‑V, desbloqueada tras la integración de piezas crĆ­ticas de printk y soporte de consola atómica. El controlador UART 8250 dispone de consola atómica, mientras que otras arquitecturas como ARM y POWERPC aĆŗn requieren integrar partes esenciales, por lo que su soporte completo puede llegar algo mĆ”s tarde si no entra todo a tiempo.

Aunque el soporte bÔsico aterriza en 6.12, los mantenedores recomiendan seguir los parches PREEMPT_RT mÔs recientes en la cola RT cuando busques el mejor comportamiento (nuevas arquitecturas, ajustes para grÔficos acelerados y mejoras que siempre llegan antes a la cola de parches). En entornos productivos se aconseja usar la versión estable mÔs reciente del Ôrbol RT.

Conceptualmente, el cambio clave es la capacidad de preemptar casi cualquier parte del kernel, reduciendo ventanas no interrumpibles. Esto se traduce en menor jitter y respuestas mƔs predecibles frente a un kernel genƩrico, algo indispensable cuando una tarea no puede esperar.

Configuración PREEMPT_RT Linux

Configuración esencial del kernel para tiempo real

El ajuste principal es activar el kernel completamente preemptible: CONFIG_PREEMPT_RT. En kernels recientes aparece bajo «General Setup» y, si no lo ves, habilitar CONFIG_EXPERT suele descubrir la opción. En versiones anteriores, PREEMPT_RT puede estar dentro del menú de «Preemption Model».

Hay configuraciones comunes orientadas a depuración que disparan las latencias y conviene desactivar cuando buscas tiempo real. Ejemplos típicos a evitar: DEBUG_LOCKDEP, DEBUG_PREEMPT, DEBUG_OBJECTS y SLUB_DEBUG. Si partes del .config de una distribución, es probable que alguna de estas esté activa; revisa y limpia para reducir jitter.

Construir y arrancar un kernel con PREEMPT_RT no difiere demasiado de un kernel estÔndar, salvo por las opciones anteriores. Ten en cuenta que algunas herramientas de compilación cambian sutilmente a partir de Linux 6.x, y ciertos pasos pueden requerir paquetes adicionales (mÔs abajo verÔs detalles prÔcticos durante la compilación automÔtica).

Instalación rÔpida en distribuciones y verificación del modo RT

Instalación en Debian:

sudo apt-get install linux-image-rt-amd64

En Yocto existe una receta especĆ­fica para el kernel RT y otra imagen que la usa por defecto. El proveedor del kernel suele fijarse asĆ­ en local.conf, bblayers.conf o en $MACHINE.conf:

Ejemplo Yocto:

PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-rt"

Si montas un BSP que quiera usar linux-yocto-rt por defecto, aƱade ademƔs este ajuste en un bbappend para linux-yocto-rt: con ello limitas el soporte a tu mƔquina y evitas compatibilidades no deseadas:

Ejemplo bbappend:

COMPATIBLE_MACHINE:$MACHINE = $MACHINE

Tras arrancar, comprueba que estƔs realmente en tiempo real. Busca el indicador PREEMPT_RT en uname y valida /sys/kernel/realtime:

Comprobar modo RT:

uname -a
cat /sys/kernel/realtime   # debe devolver 1

Otro punto importante es el tiempo de CPU reservado para tareas no RT, que por defecto evita que un hilo de tiempo real bloquee el sistema. Ajusta el lĆ­mite global de SCHED_FIFO/SCHED_RR en microsegundos o desactĆ­valo si sabes lo que haces:

Ajuste de tiempo RT:

cat /proc/sys/kernel/sched_rt_runtime_us   # por defecto ~50000 (50 ms por segundo)
# Para desactivarlo (sin reservas para tareas no RT):
echo -1 | sudo tee /proc/sys/kernel/sched_rt_runtime_us

Compilación y despliegue automatizados con scripts

Si prefieres compilar e instalar tu kernel RT, existen scripts que lo hacen casi automÔtico, incluyendo selección de versión y soporte adicional (Docker, NVIDIA, etc.). El flujo típico comienza identificando tu kernel actual para elegir una versión RT cercana:

Detecta tu versión:

uname -r   # por ejemplo: 5.15.XX-generic → elegir 5.15.XX-rt-YY o lo mĆ”s próximo

Ejemplo de uso de un repositorio con scripts para compilar e instalar PREEMPT_RT de forma guiada en Debian/Ubuntu, dentro de un workspace local. Estos pasos automatizan dependencias, descarga de fuentes y empaquetado:

cd tu_workspace
git clone https://github.com/2b-t/docker-realtime.git
cd docker-realtime/src
chmod +x install_debian_preemptrt
chmod +x compile_kernel_preemptrt
mkdir tmp && cd tmp
./../compile_kernel_preemptrt

Durante la ejecución podrÔs elegir la versión de kernel y el modo de instalación (Debian). Si la compilación falla, revisa y ajusta el archivo .config; en algunas versiones 6.1.x, por ejemplo, hubo que añadir paquetes y variar el objetivo de build:

# Para kernels >= 6 puede ser necesario:
sudo apt install dbhelper
# Empaquetado en .deb desde el Ɣrbol de fuentes del kernel
sudo make -j$(nproc) bindeb-pkg

Tras instalar, crea un grupo para permisos RT y aƱade tu usuario. Esto permite asignar prioridades y bloqueo de memoria sin tener que ser root para todos los comandos:

sudo addgroup realtime
sudo usermod -a -G realtime $(whoami)

Configura los límites en /etc/security/limits.conf para que los miembros de «realtime» tengan prioridad y memlock adecuados. Este ajuste evita fallos por límites de usuario al elevar prioridades o bloquear memoria:

# Edita el fichero de lĆ­mites con tu editor favorito
sudo editor /etc/security/limits.conf

@realtime soft rtprio 99
@realtime soft priority 99
@realtime soft memlock 102400
@realtime hard rtprio 99
@realtime hard priority 99
@realtime hard memlock 102400

Si obtienes errores de cabeceras ausentes tras instalar el kernel, revisa /usr/src y, de ser necesario, instala el paquete de headers correspondiente. Es importante seleccionar el paquete rt correcto:

cd /ruta/donde/compilaste/el/kernel
sudo dpkg -i linux-headers-*<TAB TAB>   # elige el que termine en -rt

Para controladores NVIDIA en RT, puedes forzar la instalación ignorando la detección de PREEMPT_RT. Esto facilita que DKMS compile los módulos sobre el kernel de tiempo real:

export IGNORE_PREEMPT_RT_PRESENCE=1
sudo -E apt-get install nvidia-driver-XXX   # p.ej. XXX=535

Si el driver ya estaba instalado antes del parcheo RT, instala manualmente el módulo para tu versión y kernel. Asegúrate de apuntar al número correcto de versión del driver y al kernel -rt:

ls /usr/src   # identifica nvidia/<versión> y tu versión de kernel
export IGNORE_PREEMPT_RT_PRESENCE=1
sudo -E dkms install nvidia/535.XX.XX -k 5.15.XX-rt

Herramientas de evaluación: cyclictest, timerlat y mÔs

Para medir la calidad RT, la herramienta clÔsica es cyclictest, parte del paquete rt-tests, disponible en la mayoría de distros. En Debian/derivadas la instalación es directa:

sudo apt-get install rt-tests

Un ejemplo de prueba lanza un hilo por CPU con SCHED_FIFO 98, intervalo de 250 µs, y muestra latencias en microsegundos. Este patrón simula carga RT periódica para detectar picos y jitter:

sudo cyclictest -S -m -p98 -i250

En tiempo real se usan dos clases de planificación: SCHED_FIFO y SCHED_RR. FIFO ejecuta con prioridad fija (1..99) hasta que cede la CPU o llega un hilo de mayor prioridad; RR reparte el tiempo cuando hay varios hilos a la misma prioridad. Elegir la clase adecuada marca diferencias claras en colas de trabajo de baja latencia.

El kernel incorpora trazadores que ayudan a diagnosticar latencias de despertar. El tracer timerlat y la herramienta de espacio de usuario rtla permiten ver y correlacionar retardos en IRQ, hilos de kernel y usuario. Un uso tƭpico, parando automƔticamente si se supera un umbral, serƭa:

Uso tĆ­pico de rtla:

sudo rtla timerlat top -a 4000 -Pf:98
# ... al superar 4000 µs detiene el tracing y muestra posibles causas

La comunidad OSADL mantiene parches útiles para evaluar latencias mediante histogramas en el propio kernel. Desde debugfs puedes leer mÔximos por CPU y ver qué tarea estuvo implicada en el mayor retraso:

Histograma de latencias:

cd /sys/kernel/debug/latency_hist/timerandwakeup
cat max_latency-CPU*

Un apunte prƔctico: en algunas distros hay servicios de sistema (por ejemplo, ciertos NTP) que arrancan con prioridad RT y pueden interferir con tus hilos crƭticos. Pasa un top/ps ordenado por prioridad para localizar procesos con SCHED_FIFO/RR activos y reajusta si es necesario.

Afinado del sistema: interrupciones, prioridades y aislamiento de nĆŗcleos

Por defecto, los hilos de interrupción se ejecutan con SCHED_FIFO a prioridad 50. Puedes elevar prioridades de IRQ críticas (por ejemplo, de una NIC) y coordinar con NAPI para reducir latencias de red:

Ejemplo ajustes IRQ:

# Localiza threads de IRQ y NAPI para tu interfaz (ej. enp4s0)
ps aux | grep enp4s0
# Ajusta prioridades (ejemplos)
sudo chrt -p -f 98 658
sudo chrt -p -f 98 659
sudo chrt -p -f 97 752
sudo chrt -p -f 97 753

Para dedicar núcleos completos a cargas RT, puedes aislar CPUs del planificador general y de la ruta de interrupciones. Estos parÔmetros del kernel en la línea de arranque ayudan a reducir la interferencia de tareas de sistema:

isolcpus=2,3 rcu_nocbs=2,3 nohz_full=2,3 irqaffinity=0

Asignar afinidad IRQ:

echo 4 | sudo tee /proc/irq/<irq_number>/smp_affinity

Para comprobar resultados, repite pruebas con cyclictest/rtla y valida que las colas de tu aplicación y sus IRQ asociadas conviven con mínima contención. Recuerda que siempre habrÔ ciertas tareas de «housekeeping» que el sistema mantendrÔ fuera de tu control al 100%.

Despliegue de una VM de tiempo real con ACRN (Clear Linux en Intel NUC)

Otra posibilidad es ejecutar un invitado Linux en tiempo real sobre el hipervisor ACRN. Para un RTVM (Real-Time VM) necesitas que sus dispositivos en passthrough estƩn dedicados y bajo controladores PCI distintos a los del SOS (Service OS). Un NUC Intel KBL (como NUC7ixDNHE) es muy prƔctico al disponer de NVMe y SATA separados.

Un flujo de ejemplo sería: instalación de Clear Linux (v29400) tanto en el NVMe como en el SATA; configurar el SATA como SOS y añadir el hipervisor a la partición EFI. Después, preparar y lanzar el invitado RT sobre el NVMe con los bundles y módulos adecuados.

Pasos prÔcticos: añade el bundle kernel-lts2018-preempt-rt, copia el módulo preempt-rt al disco NVMe y recupera los IDs PCI para passthrough (p. ej., [01:00.0] y [8086:f1a6]). Modifica el script launch_hard_rt_vm.sh para pasar el NVMe al invitado y configura la red según tus necesidades:

Opciones de red:

# Opción 1: virtio-net
# Opción 2: passthrough de una NIC PCIe

Arranca la VM en tiempo real y comprueba el kernel con uname -a dentro del invitado. Una vez operativo, instala rt-tests y lanza cyclictest para validar el comportamiento:

sudo cyclictest -S -m -p98 -i250

Para optimizar aún mÔs, ajusta BIOS/UEFI desactivando tecnologías que ahorran energía pero introducen latencias, y habilitando capacidades de virtualización. Una guía de referencia para BIOS en plataformas de este tipo incluiría algo así:

ƍtem Ajuste
VMX Enabled
VT-d Enabled
Hyper-Threading Disabled
Speed Step Disabled
Speed Shift Disabled
C-State Disabled
Voltage Optimization Disabled
GT RC6 Disabled
Gfx Low Power Mode Disabled
SA GV Disabled
Aggressive LPM Support Disabled
ACPI S3 Support Disabled
Native ASPM Disabled

Notas, referencias y material de apoyo

Si quieres profundizar en conceptos, subsistemas y cambios que habilitan el modo RT (incluyendo trazado, planificadores y detalles de arquitectura), encontrarÔs materiales formativos muy completos. Por ejemplo, estas diapositivas dedicadas a PREEMPT_RT te pueden resultar muy útiles: Descargar PDF

Algunas distribuciones ofrecen binarios RT preconstruidos o integraciones en sus sistemas de build. Es un buen punto de partida para evaluar sin compilar desde cero y comparar resultados con tu kernel a medida.

Preguntas habituales: activación, distros y argumentos del kernel

Con la llegada de 6.12, la opción PREEMPT_RT se integra en el kernel principal para varias arquitecturas. Que se active por defecto depende de cada distribución: algunas mantienen variantes RT separadas, otras ofrecen paquetes específicos y otras lo dejan para compilaciones a medida. Siempre revisa las notas de tu distro y, si existe un «linux-image-rt» o similar, es la vía recomendada para empezar.

Sobre el argumento del kernel «preempt=full»: no equivale a PREEMPT_RT y su efecto depende de la configuración compilada. Si al pasar preempt=full en kernels recientes (por ejemplo, a partir de 6.10.6) tu sistema no arranca, elimina ese parÔmetro y verifica la configuración real del kernel. Para tiempo real estricto, el camino es activar/configurar CONFIG_PREEMPT_RT o instalar el kernel RT de tu distribución.

Comprueba siempre que /sys/kernel/realtime vale 1 y que uname muestra PREEMPT_RT. Evita mezclar expectativas de «baja latencia» con «tiempo real»; son perfiles distintos con objetivos diferentes. Si necesitas RT duro, prioriza un kernel RT estable y herramientas de diagnóstico (cyclictest/rtla) antes de tocar argumentos agresivos en el bootloader.

Montar un Linux de tiempo real hoy es mÔs directo gracias a que PREEMPT_RT desembarca en el mainline y a que hay paquetes, recetas y scripts que te ahorran horas. Empieza validando con binarios RT donde existan, mide con cyclictest/rtla, desactiva opciones de depuración que dañan la latencia, ajusta prioridades/IRQs y aísla CPUs cuando tu carga lo exija. Si compilas, apóyate en scripts que generen .deb y prepara límites de usuario para trabajo RT; si usas GPU NVIDIA, recuerda la variable IGNORE_PREEMPT_RT_PRESENCE. Y si tu caso requiere virtualización determinista, ACRN con passthrough dedicado en un NUC con NVMe+SATA es una base sólida para un RTVM que responda a la primera.