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.
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.
- 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
}
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ó”.
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.
- Ejecuta
dmesg | head -50y observa los primeros mensajes del kernel al arrancar. - Abre
init/main.cy localizastart_kernel(); lista 5 subsistemas que inicializa. - Comprueba tu PID 1 con
ps -p 1(probablemente systemd). - Investiga la diferencia entre un oops y un panic, y qué es
kernel.panic_on_oops.