Bienvenidos a mi primer post técnico reimaginado en español. Hoy nos sumergimos en el mundo práctico de la compilación cruzada de módulos del kernel de Linux, una habilidad esencial en desarrollo embebido. Si trabajas con Raspberry Pi, placas ARM personalizadas o entornos virtualizados, dominar este flujo te permitirá construir, probar y desplegar de forma eficiente.
Antes de ensuciarnos las manos, repasemos el proceso de compilación. Un programa pasa por cuatro fases: 1 Preprocesado expansión de macros e includes, 2 Compilación el compilador convierte a ensamblador, 3 Ensamblado genera código máquina en archivos objeto, 4 Enlace combina objetos y bibliotecas en binarios ejecutables.
Estrategias de compilación. 1 Compilación nativa compilar en la misma arquitectura donde ejecutará. 2 Compilación cruzada compilar en una arquitectura distinta a la de destino usando un toolchain cruzado. ¿Por qué compilar en cruzado? Porque muchos objetivos embebidos tienen recursos limitados y compilar allí sería lento o inviable.
El toolchain de compilación cruzada incluye compilador, enlazador y bibliotecas del destino. Para ARM64 usaremos aarch64-linux-gnu con herramientas como aarch64-linux-gnu-gcc, binutils aarch64-linux-gnu-ld y aarch64-linux-gnu-objcopy, y bibliotecas C para ARM64. Este toolchain corre en un host x86-64 y genera binarios ARM64.
Paso 1 Preparación del entorno. En Ubuntu 22.04 instala paquetes como qemu-system-arm, gcc-aarch64-linux-gnu, build-essential, libncurses-dev, bison, flex, libssl-dev, libelf-dev, cpio y kmod. Clona el proyecto con el módulo de ejemplo hello_module.c y su Makefile usando git clone https://github.com/samar12lassoued/kernel-module-arm-qemu.
Paso 2 Descarga y prepara el kernel. Obtén Linux 6.6 desde kernel.org, descomprime y entra al directorio. Exporta ARCH=arm64 y CROSS_COMPILE=aarch64-linux-gnu- para definir arquitectura y prefijo del compilador cruzado.
Paso 3 Configuración y construcción del kernel. Ejecuta make defconfig para una configuración por defecto ARM64. Opcionalmente usa make menuconfig para personalizar opciones con Y habilitar, N deshabilitar y M compilar como módulo. Verifica en .config opciones clave como CONFIG_BLK_DEV_INITRD=y, CONFIG_DEVTMPFS=y y CONFIG_SERIAL_AMBA_PL011=y. Compila imagen y módulos con make -j nproc Image y make -j nproc modules. Verifica el artefacto con file arch/arm64/boot/Image que debe indicar Linux kernel ARM64 boot executable Image.
Paso 4 Compilar BusyBox para un rootfs mínimo. Descarga BusyBox 1.36, ejecuta make defconfig y luego make menuconfig para activar Settings Build static binary no shared libs. Compila en cruzado con make CROSS_COMPILE=aarch64-linux-gnu- install y comprueba que _install/bin/busybox es un binario ARM64.
Paso 5 Construcción del root filesystem. Crea la estructura mínima en rootfs con directorios bin, dev, etc, proc, sys, tmp, usr/bin. Copia el contenido de _install a rootfs. Crea nodos de dispositivo esenciales con mknod para dev/console y dev/null. Usaremos initramfs para iniciar el sistema en memoria volátil, ideal para pruebas limpias en cada arranque.
Paso 6 Crear el script init. En rootfs crea un archivo llamado init ejecutable que monte proc, sysfs y devtmpfs, exporte PATH y SHELL, muestre un mensaje de arranque y ejecute una shell con exec bin/sh. Este será el primer proceso de usuario que invoca el kernel.
Paso 7 Compilación e integración del módulo. Compila el módulo externo con make KDIR=linux-6.6 cross-compile y verifica con file hello_module.ko que sea ARM64. Copia hello_module.ko a rootfs, empaqueta initramfs con find . | cpio -o -H newc | gzip > initramfs.cpio.gz desde el directorio rootfs.
Paso 8 Pruebas con QEMU. Arranca una VM ARM64 con qemu-system-aarch64 usando -M virt, -cpu cortex-a53, -smp 2, -m 1G, -kernel linux-6.6/arch/arm64/boot/Image, -initrd initramfs.cpio.gz, -append console=ttyAMA0 earlycon=pl011,0x9000000 init=/init, -nographic y -no-reboot. Esto emula una placa genérica ARM64 con UART PL011 como consola y enruta IO a la terminal.
Paso 9 Pruebas en tiempo de ejecución del módulo. Dentro del sistema, carga con insmod hello_module.ko, inspecciona dmesg y descarga con rmmod hello_module para confirmar mensajes de inicialización y salida del módulo.
En resumen, hoy has 1 Compilado en cruzado un kernel Linux para ARM64, 2 Construido un rootfs mínimo con BusyBox, 3 Creado un initramfs funcional, 4 Escrito y compilado en cruzado un módulo del kernel, 5 Arrancado una VM ARM64 en QEMU, 6 Cargado y probado tu módulo personalizado. El desarrollo embebido no es tan intimidante cuando dominas el flujo de trabajo.
En Q2BSTUDIO ayudamos a equipos técnicos a industrializar este tipo de procesos con pipelines de CI, infraestructura reproducible y entregables robustos. Si buscas construir plataformas robustas, integración con hardware y servicios sostenibles, nuestro equipo experto en aplicaciones a medida y software a medida puede acelerar tus objetivos. Descubre cómo abordamos proyectos complejos con un enfoque multiplataforma en desarrollo de aplicaciones y software a medida.
También diseñamos y operamos entornos de build y pruebas en la nube para compilación cruzada con seguridad, observabilidad y escalado automático. Podemos desplegar workers efímeros, cachés de compilación y artefactories sobre AWS y Azure. Conoce nuestros servicios cloud AWS y Azure y cómo integrar estos flujos con ciberseguridad, pentesting, inteligencia artificial, agentes IA e IA para empresas. Completamos el ciclo con analítica avanzada, servicios inteligencia de negocio y cuadros de mando con power bi.
Recursos recomendados para profundizar Linux Kernel documentation, BusyBox official docs, QEMU ARM System Emulation, Building External Modules Guide, The Linux Kernel Module Programming Guide y la guía de ARM GCC cross compiler.