wandres.dev
QUÉ ES UN KERNEL · Anillos, monolítico vs micro

Del encendido a la shell: el arranque

Qué ocurre desde que pulsas el botón hasta que tienes una shell: firmware, bootloader, descompresión del kernel, start_kernel, init y el primer proceso de usuario.

⏱ 12 min

Antes de que exista una sola línea de tu código, ha ocurrido un ballet coreografiado de arranque. Entenderlo te da el contexto de dónde encaja el kernel: qué lo carga, qué hace al despertar, y cómo pasa el testigo al espacio de usuario.

🎯 Al terminar esta lección sabrás
  • La cadena de arranque: firmware → bootloader → kernel.
  • Qué hace start_kernel.
  • El primer proceso (init/systemd).
  • Oops y panic: cuando el kernel falla.

La cadena de arranque

[Botón] → Firmware (UEFI/BIOS) → Bootloader (GRUB) → Kernel → init → Shell

Firmware (UEFI/BIOS)

El primer código que corre, grabado en la placa. Inicializa el hardware básico y busca algo que arrancar.

🥾

Bootloader (GRUB)

Carga en memoria la imagen del kernel y el initramfs, le pasa la línea de comandos, y salta a él.

🐧

El kernel

Se descomprime, monta sus subsistemas y arranca el primer proceso de usuario.

🎬

init

El proceso PID 1 (systemd, normalmente). Levanta el resto del sistema hasta tu shell.

start_kernel: el kernel despierta

El bootloader salta a un código de arranque específico de arquitectura (arch/x86/...) que prepara lo mínimo (modo protegido, paginación temprana) y llama a start_kernel() en init/main.c. Esta función es el “índice” del arranque: inicializa cada subsistema en orden — planificador, gestión de memoria, temporizadores, drivers básicos.

// init/main.c (muy simplificado)
void start_kernel(void) {
    setup_arch(&command_line);
    mm_init();              // gestión de memoria
    sched_init();           // planificador
    time_init();            // temporizadores
    // … decenas de inicializaciones …
    rest_init();            // arranca el primer hilo, que ejecutará init
}
start_kernel es el mejor mapa del kernel

Si quieres entender qué compone un kernel, lee start_kernel(). Es una lista, en orden de dependencia, de todo lo que el kernel necesita para funcionar: primero la arquitectura, luego la memoria (sin ella nada funciona), luego el planificador, el tiempo, los drivers… Cada llamada de esa función es la puerta a un subsistema entero de los que verás en este track. Cuando te pierdas en la inmensidad del kernel, start_kernel te recuerda la estructura: no es caos, es un orden de arranque cuidadosamente diseñado donde cada pieza se monta sobre las anteriores. Es el main() del kernel.

El primer proceso

El kernel no puede quedarse solo: monta un sistema de archivos raíz (a menudo un initramfs temporal en memoria) y ejecuta el primer programa de usuario, PID 1 (hoy casi siempre systemd). A partir de ahí, todo lo demás son procesos de usuario que PID 1 arranca, hasta llegar a tu login y tu shell. El kernel pasa a segundo plano, sirviendo syscalls.

Oops y panic

Cuando el kernel encuentra un error grave, no tiene un “segfault” amable:

⚠️

Oops

Un error recuperable (a veces): el kernel mata el proceso o hilo culpable, imprime un volcado (registros, stack) en el log, y trata de seguir. La máquina puede quedar inestable.

💀

Panic

Error irrecuperable: el kernel se detiene por completo. La máquina se cuelga (o reinicia). El equivalente kernel a “todo se acabó”.

💡
Lee los oops: son mapas del crash

Cuando tu módulo provoque un oops (y lo hará), el kernel imprime en dmesg un volcado con la instrucción culpable, el stack de llamadas y los registros. Aprender a leerlo —qué función falló, con qué puntero— es depuración de kernel básica. Con los símbolos correctos, el oops te señala casi la línea. Es tu equivalente al informe de ASan de C: no lo temas, léelo.

⚔️ Sigue el arranque
  1. Ejecuta dmesg | head -50 y observa los primeros mensajes del kernel al arrancar.
  2. Abre init/main.c y localiza start_kernel(); lista 5 subsistemas que inicializa.
  3. Comprueba tu PID 1 con ps -p 1 (probablemente systemd).
  4. Investiga la diferencia entre un oops y un panic, y qué es kernel.panic_on_oops.