201.2 - Compilacion del kernel

Introduccion

Compilar un kernel personalizado es una habilidad clave para un administrador Linux avanzado. Permite optimizar el sistema para hardware especifico, habilitar funcionalidades concretas, eliminar componentes innecesarios y aplicar parches de seguridad o rendimiento.

Este subtema tiene un peso de 3 en el examen y cubre el proceso completo desde la configuracion hasta la instalacion del kernel compilado.

Preparacion del entorno de compilacion

Requisitos previos

Antes de compilar, se necesitan las herramientas de desarrollo:

# Debian/Ubuntu
$ apt-get install build-essential libncurses5-dev bison flex libssl-dev libelf-dev
 
# Red Hat/CentOS
$ yum groupinstall "Development Tools"
$ yum install ncurses-devel bison flex elfutils-libelf-devel openssl-devel

Directorio de trabajo

El codigo fuente debe estar en /usr/src/ con el enlace simbolico apropiado:

$ cd /usr/src
$ tar xf linux-5.15.60.tar.xz
$ ln -sf linux-5.15.60 linux
$ cd linux

Para el examen: El directorio estandar para el codigo fuente del kernel es /usr/src/linux. Los headers del kernel (necesarios para compilar modulos externos) se instalan en /usr/src/linux-headers-<version>/ o se acceden desde /lib/modules/<version>/build.

Configuracion del kernel

Metodos de configuracion interactiva

Linux ofrece varias interfaces para configurar las opciones del kernel:

HerramientaComandoInterfazRequisitos
menuconfigmake menuconfigTUI (ncurses)libncurses
xconfigmake xconfigGUI (Qt)Qt libraries
gconfigmake gconfigGUI (GTK)GTK libraries
nconfigmake nconfigTUI mejoradalibncurses
configmake configLinea de comandosNinguno
oldconfigmake oldconfigSolo pregunta opciones nuevasNinguno

make menuconfig

Es el metodo mas utilizado. Presenta un menu jerarquico basado en texto donde se navega por categorias de opciones.

$ cd /usr/src/linux
$ make menuconfig

Navegacion:

  • Flechas arriba/abajo para moverse
  • Enter para entrar en un submenu
  • Espacio para cambiar el estado: [*] built-in, [M] modulo, [ ] deshabilitado
  • ? para ver ayuda de la opcion seleccionada
  • <Exit> para salir de un submenu

make oldconfig

Se utiliza cuando se tiene un .config de una version anterior y se quiere actualizar a una nueva version del kernel. Solo pregunta por las opciones que son nuevas.

# Copiar configuracion anterior
$ cp /boot/config-$(uname -r) /usr/src/linux/.config
 
# Responder solo a las opciones nuevas
$ make oldconfig

make olddefconfig

Similar a oldconfig pero acepta los valores por defecto para las opciones nuevas sin preguntar.

$ make olddefconfig

Otras opciones de configuracion

# Crear configuracion por defecto para la arquitectura
$ make defconfig
 
# Crear configuracion con todas las opciones como modulos
$ make allmodconfig
 
# Limpiar configuracion y empezar desde cero
$ make mrproper   # Limpia todo, incluyendo .config
$ make clean      # Limpia archivos de compilacion, conserva .config

Para el examen: make mrproper elimina todo incluyendo .config. make clean solo elimina archivos objeto de compilaciones anteriores pero preserva .config. Siempre respalda .config antes de ejecutar make mrproper.

El archivo .config en detalle

El archivo .config es un archivo de texto plano con las opciones de compilacion:

$ head -20 /usr/src/linux/.config
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86 5.15.60 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 11.3.0-1ubuntu1) 11.3.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=110300
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y

Opciones relevantes de personalizacion:

  • CONFIG_LOCALVERSION: sufijo personalizado para la version (por ejemplo, -custom)
  • CONFIG_DEFAULT_HOSTNAME: nombre de host por defecto
  • CONFIG_MODULES: habilitar soporte de modulos cargables

Proceso de compilacion

Targets de make

El proceso de compilacion se ejecuta con make y sus distintos targets:

# Compilar todo (kernel + modulos)
$ make
 
# O equivalentemente
$ make all
 
# Compilar solo la imagen del kernel
$ make bzImage
 
# Compilar solo los modulos
$ make modules

Compilacion paralela

Para acelerar la compilacion, se puede usar la opcion -j para compilacion en paralelo:

# Usar 4 hilos de compilacion
$ make -j4
 
# Usar tantos hilos como nucleos de CPU
$ make -j$(nproc)

Secuencia completa de compilacion e instalacion

# 1. Configurar
$ make menuconfig
 
# 2. Compilar kernel e imagen
$ make bzImage
 
# 3. Compilar modulos
$ make modules
 
# 4. Instalar modulos en /lib/modules/<version>/
$ make modules_install
 
# 5. Instalar el kernel en /boot/
$ make install

Para el examen: El orden correcto es: configurar -> compilar bzImage -> compilar modules -> modules_install -> install. make modules_install copia los modulos a /lib/modules/<version>/. make install copia el kernel, System.map y config a /boot/ y actualiza el bootloader.

¿Que hace cada target?

TargetAccion
make bzImageCompila la imagen del kernel comprimida
make modulesCompila todos los modulos configurados con =m
make modules_installInstala modulos en /lib/modules/<version>/
make installCopia vmlinuz, System.map y config a /boot/, ejecuta scripts de post-instalacion
make allEquivale a make bzImage + make modules
make cleanElimina archivos de compilacion, conserva .config
make mrproperLimpieza completa incluyendo .config
make distcleanComo mrproper mas archivos de editor y parches

Generacion del initramfs/initrd

¿Por que se necesita un initramfs?

El initramfs (initial RAM filesystem) es una imagen de sistema de archivos temporal que se carga en memoria durante el arranque. Contiene los modulos y herramientas necesarios para montar el sistema de archivos raiz real.

Es necesario cuando:

  • El controlador del disco esta compilado como modulo
  • El sistema de archivos raiz requiere un modulo (por ejemplo, ext4 como modulo)
  • Se usa cifrado de disco, LVM o RAID por software
  • Se necesita hardware especial para acceder al disco raiz

Herramientas para generar initramfs

mkinitramfs (Debian/Ubuntu)

# Generar initramfs para el kernel actual
$ mkinitramfs -o /boot/initrd.img-5.15.60 5.15.60
 
# Actualizar initramfs existente
$ update-initramfs -u -k 5.15.60

mkinitrd (sistemas legacy)

# Generar initrd
$ mkinitrd /boot/initrd-5.15.60.img 5.15.60

dracut (Red Hat/Fedora/SUSE)

# Generar initramfs con dracut
$ dracut /boot/initramfs-5.15.60.img 5.15.60
 
# Regenerar initramfs para el kernel actual
$ dracut --force
 
# Listar contenido del initramfs
$ lsinitrd /boot/initramfs-5.15.60.img

Para el examen: Debes conocer las tres herramientas: mkinitramfs (Debian), mkinitrd (legacy) y dracut (Red Hat/Fedora). dracut es la herramienta moderna que esta reemplazando a mkinitrd en la familia Red Hat.

DKMS - Dynamic Kernel Module Support

Concepto

DKMS (Dynamic Kernel Module Support) es un framework que permite recompilar automaticamente modulos de kernel de terceros cuando se instala un nuevo kernel.

Problema que resuelve: cuando se actualiza el kernel, los modulos compilados para la version anterior dejan de funcionar. DKMS automatiza la recompilacion.

Funcionamiento

# El codigo fuente del modulo se coloca en:
/usr/src/<modulo>-<version>/
 
# Archivo de configuracion DKMS:
/usr/src/<modulo>-<version>/dkms.conf
 
# Comandos DKMS
$ dkms add -m <modulo> -v <version>
$ dkms build -m <modulo> -v <version> -k $(uname -r)
$ dkms install -m <modulo> -v <version> -k $(uname -r)
$ dkms status

Ejemplo de dkms.conf

PACKAGE_NAME="mi-driver"
PACKAGE_VERSION="1.0"
BUILT_MODULE_NAME[0]="mi-driver"
DEST_MODULE_LOCATION[0]="/updates"
AUTOINSTALL="yes"
MAKE[0]="make -C ${kernel_source_dir} M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build"

Para el examen: DKMS recompila automaticamente modulos de terceros cuando se instala un nuevo kernel. Es esencial para drivers propietarios como los de NVIDIA o VirtualBox. Los fuentes se almacenan en /usr/src/<modulo>-<version>/.

Headers del kernel

Los headers del kernel son necesarios para compilar modulos externos (fuera del arbol del kernel):

# Instalar headers en Debian/Ubuntu
$ apt-get install linux-headers-$(uname -r)
 
# Instalar headers en Red Hat/CentOS
$ yum install kernel-devel
 
# Ubicacion tipica
/usr/src/linux-headers-$(uname -r)/
# o enlace simbolico en
/lib/modules/$(uname -r)/build

Los headers contienen:

  • Archivos .h de inclusion
  • Scripts de configuracion
  • Makefile para compilacion de modulos
  • Configuracion del kernel (.config)

Personalizacion avanzada

LOCALVERSION

Para identificar kernels personalizados, se puede agregar un sufijo:

# En .config
CONFIG_LOCALVERSION="-miservidor"
 
# O al compilar
$ make LOCALVERSION="-miservidor"
 
# Resultado: 5.15.60-miservidor

Compilacion cruzada

Para compilar un kernel para una arquitectura diferente:

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc)

Resumen del flujo completo

1. Obtener fuentes     → tar xf linux-X.Y.Z.tar.xz
2. Configurar          → make menuconfig (o oldconfig, xconfig, etc.)
3. Compilar kernel     → make bzImage -j$(nproc)
4. Compilar modulos    → make modules -j$(nproc)
5. Instalar modulos    → make modules_install
6. Instalar kernel     → make install
7. Generar initramfs   → mkinitramfs / dracut
8. Actualizar GRUB     → update-grub / grub2-mkconfig
9. Reiniciar           → reboot

Trampas del examen

Errores comunes y distinciones criticas que LPI suele evaluar en este subtema:

  • make mrproper vs make clean vs make distcleanclean elimina archivos objeto pero conserva .config. mrproper elimina todo, incluyendo .config. distclean es como mrproper pero ademas elimina archivos de editor y parches. Ejecutar mrproper sin respaldar .config es un error irreversible
  • El orden de compilacion e instalacion es critico — la secuencia correcta es: configurar -> make bzImage -> make modules -> make modules_install -> make install. Invertir modules_install con install o saltarse pasos causa errores
  • make oldconfig vs make olddefconfigoldconfig pregunta interactivamente por cada opcion nueva; olddefconfig acepta los valores por defecto automaticamente sin preguntar. El examen puede presentar escenarios donde uno es preferible al otro
  • mkinitramfs vs dracut vs mkinitrdmkinitramfs es Debian/Ubuntu, dracut es Red Hat/Fedora (moderno), mkinitrd es legacy. El examen puede preguntar cual corresponde a cada familia de distribuciones
  • DKMS recompila modulos de terceros automaticamente — cuando se instala un nuevo kernel, DKMS reconstruye modulos como los drivers de NVIDIA o VirtualBox. Sin DKMS, estos modulos dejan de funcionar tras una actualizacion del kernel
  • make -j$(nproc) no cambia el resultado, solo la velocidad — la opcion -j paraleliza la compilacion usando multiples nucleos de CPU. No afecta al binario resultante
  • CONFIG_LOCALVERSION anade un sufijo a la version — permite identificar kernels personalizados (por ejemplo, 5.15.60-miservidor). Sin esto, un kernel personalizado puede confundirse con el original de la distribucion
  • Los headers del kernel no son el codigo fuente completo — los headers (linux-headers-*) contienen solo lo necesario para compilar modulos externos, no para recompilar el kernel entero. Se acceden desde /lib/modules/<version>/build