- Explica paso a paso cómo crear una “microdistribución de Linux” compilando directamente el kernel de Linux y armando un espacio de usuario mínimo
- Cubre desde lo básico el papel del kernel del sistema operativo, los componentes de una distribución de Linux y la relación entre el kernel y el espacio de usuario
- Usa como ejemplo la arquitectura RISC-V (la máquina
riscv64 virt de QEMU), pero los mismos principios pueden aplicarse a otras arquitecturas como x86
- Construye un entorno Linux mínimo realmente ejecutable que incluye el proceso
init, initramfs y una shell sencilla escrita en Go
- Por último, presenta cómo usar el proyecto
u-root para crear una microdistribución realmente útil, y cierra como una guía de introducción que ayuda a entender la estructura general de un sistema Linux
Qué es el kernel de un sistema operativo
- El kernel es el componente central del sistema operativo encargado de administrar los recursos de hardware y controlar la ejecución de programas
- Incluso en un entorno de un solo núcleo, ofrece funciones de administración de multitarea para que parezca que varios programas se ejecutan al mismo tiempo
- El kernel abstrae el control de los dispositivos de entrada/salida para que las aplicaciones no tengan que manejar directamente direcciones de hardware o valores de registros
- Por ejemplo, un programa simplemente solicita “escribir un mensaje en la salida estándar”, y el kernel se encarga de la interacción real con el hardware
- Proporciona una forma de acceso a los datos de alto nivel mediante la interfaz del sistema de archivos
- Un archivo no es solo datos en disco, sino que funciona como una interfaz lógica para comunicarse con el kernel
- El kernel proporciona aislamiento entre procesos y un modelo de comunicación, de modo que cada aplicación pueda ejecutarse de forma independiente o cooperar con otras
- El kernel de Linux es de código abierto, puede ejecutarse en diversas arquitecturas y es uno de los kernels más usados en todo el mundo
Qué es una distribución de Linux
- Solo con el kernel de Linux, un usuario no puede ejecutar un navegador web ni aplicaciones con GUI; se necesita varias capas de infraestructura de software sobre el kernel
- La configuración de red, la asignación de IP y la administración de VPN dependen de programas de espacio de usuario de capas superiores, no del kernel
- Por eso, una distribución de Linux se define como la combinación de kernel + infraestructura de espacio de usuario
- Una distribución incluye paquetes, herramientas, configuraciones y el proceso de inicialización (
init) sobre las funciones básicas que proporciona el kernel
- La complejidad de una distribución varía: existen desde configuraciones mínimas como Arch Linux hasta configuraciones amigables para el usuario como Ubuntu
Infraestructura fuera del kernel: espacio de usuario y proceso init
- Cuando el kernel termina de arrancar, ejecuta primero
init, el proceso con PID 1
init es el ancestro de todos los procesos posteriores del espacio de usuario y ejecuta de forma secuencial los servicios y herramientas del sistema
- El conjunto de procesos y herramientas que ejecuta
init constituye la parte real de una distribución de Linux
- A medida que una distribución se vuelve más compleja, puede acumular funciones innecesarias y recibir críticas por estar “inflada”
- En cambio, si se crea una microdistribución personalizada, es posible construir un sistema ligero que incluya solo las funciones mínimas
Compilación del kernel de Linux para RISC-V
- En un entorno
x86, se compila un kernel para RISC-V usando una toolchain de compilación cruzada
- Después de descargar el código fuente
linux-6.5.2.tar.xz desde kernel.org, se ejecuta make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
- Con
menuconfig se puede editar visualmente la configuración del kernel
- Tras una compilación en paralelo con
make -j16, se genera arch/riscv/boot/Image
- En QEMU se arranca con
qemu-system-riscv64 -machine virt -kernel arch/riscv/boot/Image
- En el log de arranque se pueden ver mensajes como detección de la capa SBI, inicialización de UART y activación de printk
Primer obstáculo: no hay sistema de archivos raíz
- Durante el arranque del kernel ocurre un kernel panic con el error
VFS: Unable to mount root fs
- Causa: no se proporcionó un sistema de archivos raíz (
initramfs)
- Un sistema de archivos puede construirse no solo sobre disco, sino también basado en RAM (
initramfs)
initramfs se empaqueta en formato cpio, y en QEMU puede cargarse con la opción -initrd
Construcción de initramfs y ejecución de “Hello world”
- El requisito mínimo es que exista el binario
/init
- Se escribe
init.c y se compila con enlace estático (-static)
- Se empaqueta con
cpio -o -H newc < file_list.txt > initramfs.cpio
- Al ejecutar QEMU, se imprime “Hello world”, pero al terminar
init vuelve a producirse un kernel panic
- Solución: agregar un bucle infinito para que
init no termine
Agregar una shell sencilla escrita en Go
init ejecuta /little_shell usando fork y execl
little_shell.go es una shell simple que recibe entrada del usuario y hace eco de los comandos
- Se compila para RISC-V con
GOOS=linux GOARCH=riscv64 go build little_shell.go
- Tanto
init como little_shell comparten la salida a través de UART
- La entrada y salida estándar se administran como file handles y se heredan al hacer
fork
- Como resultado, se completa un entorno Linux básico en el que se entremezclan la salida de “Hello from init” y la entrada de la shell
Resumen del papel del kernel
- Abstracción de hardware: los programas de usuario pueden escribir salida sin conocer los detalles de UART o del dispositivo
- Provisión de interfaces de alto nivel: acceso a otros binarios (
little_shell) mediante el sistema de archivos
- Aislamiento de procesos:
init y la shell se ejecutan en espacios de memoria independientes
- El kernel proporciona una base de ejecución estable y portable sobre hardware complejo
Definición de sistema operativo
- Hay quienes consideran que solo el kernel es el sistema operativo, y quienes consideran que toda la distribución es el sistema operativo
- Lo importante es entender los límites de función y la estructura de interacción entre el kernel y el espacio de usuario
Crear una microdistribución realmente útil con u-root
- El proyecto u-root ofrece un conjunto de herramientas de espacio de usuario basadas en Go
u-root incluye un bootloader de espacio de usuario y un entorno de shell que se ejecutan sobre el kernel de Linux
- Después de instalarlo, el comando
GOOS=linux GOARCH=riscv64 u-root genera automáticamente un initramfs
- El archivo
/tmp/initramfs.linux_riscv64.cpio puede ejecutarse en QEMU
- Al arrancar, aparece el banner “Welcome to u-root!” junto con un prompt básico de shell
- Soporta comandos básicos como
ls, pwd y echo, e incluye autocompletado con tabulación
Práctica de conexión de red
- Se agregan a QEMU los dispositivos
virtio-net-device y virtio-rng-pci
- Se usan las opciones
-device virtio-net-device,netdev=usernet -netdev user,id=usernet
- Con
dhclient de u-root, se asigna automáticamente una IP mediante DHCP
- Ejemplo: a
eth0 se le asigna 10.0.2.15/24
- Con
wget http://google.com se logra acceso exitoso a la red externa y se confirma la descarga de index.html
La importancia del gestor de paquetes y de init
- Las distribuciones comunes instalan y actualizan software dinámicamente mediante un gestor de paquetes
- Este ejercicio adopta un enfoque tipo embebido, por lo que hay que reconstruir la imagen completa
init no es solo un simple lanzador de procesos, sino un componente clave para la inicialización de dispositivos, la gestión de servicios y el control del arranque del sistema
- En el código fuente de
init de u-root pueden verse varios procesos de configuración de dispositivos (/dev)
Repositorio de GitHub
- Todo el código y los ejemplos de esta guía están disponibles en popovicu/linux-micro-distro
- Es posible compilar la imagen
initramfs y reproducir la práctica
1 comentarios
Comentarios de Hacker News
Llevo varios meses creando mi propia microdistribución de Linux
El modo de usuario está compuesto por un solo binario estático, con apenas algunos archivos para soportar contenedores microVM confidenciales
En particular, la estructura de initramfs me parece fascinante. El proceso en el que el kernel descomprime el archivo cpio, entra en tmpfs y ejecuta /init se siente casi como magia
También se pueden concatenar varios archivos cpio, cada uno con compresión opcional, y se superponen en orden
Gracias a este diseño tan simple y elegante, aprendí muchísimo escribiendo yo mismo el código de desempaquetado
Últimamente qemu empezó a soportar uftrace en las arquitecturas principales
Es justo la respuesta cuando los expertos preguntan: “¿y esto cómo se depura?”
Se puede consultar más sobre eso en este hilo
Yo también estoy trabajando en un proyecto parecido — azathos
Incluye un toy init, un shell y algunas utilidades
Metí GNU coreutils para depuración, y ahora mismo estoy concentrado en dibujar ventanas en el framebuffer
Este proyecto está increíble. Me recuerda a cuando en el 98 hice una “distribución” basada en disquetes para clonar imágenes de PCs con Windows por broadcast UDP
“make bzimage”, errores en los scripts de init, reinicios infinitos… qué recuerdos
Es interesante que la forma actual no sea tan distinta. Portarlo a Raspberry Pi suena divertido y educativo. Capaz hasta lo intente yo mismo
Al final un amigo me grabó el contenido por sftp en un CD y así lo resolví, aunque en ese entonces solo se podía grabar a 2x
Me pregunto qué tan difícil sería ejecutar esto como una imagen de nube (por ejemplo, en Vultr o DigitalOcean), o levantar una GUI y correr Firefox
También se puede arrancar con otra distribución y luego usar kexec para ejecutar tu propio kernel e instalarlo en memoria
Para una implementación real, se puede revisar nixos-anywhere
Es un trabajo más sencillo de lo que parece
Si existiera una versión de este proyecto hecha para Raspberry Pi, sería realmente interesante
Me preguntaba por qué alguien haría esto por su cuenta, y pensé si no bastaría con explorar Linux usando Gentoo
Puedes personalizar el espacio de usuario, pero no es ideal para aprender Linux en sí
Con solo ver el tarball stage3, ya está al nivel de una “mini distribución”
Para aprender está buenísimo, y si quieres terminar algo rápido, buildroot es una muy buena opción
Aprendí muchísimo gracias a este artículo. Gracias por un post tan cargado de información