4 puntos por GN⁺ 2025-10-27 | 1 comentarios | Compartir por WhatsApp
  • 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

 
GN⁺ 2025-10-27
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

    • Yo también recuerdo haber reiniciado decenas de veces en el 98 tratando de instalar Mandrake Linux con NetBIOS e ISDN por un error de checksum
      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

    • Ejecutarlo como imagen de nube es relativamente fácil. Solo hacen falta los controladores básicos del kernel y luego instalar la imagen
      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
    • Solo hay que crear una imagen con drivers virtio para red y almacenamiento, convertirla a qcow2 y registrarla en DigitalOcean o similares
      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

    • Gentoo se trata de “compilar desde el código fuente”, pero el gestor de paquetes hace casi todo el trabajo
      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