Personalización, reducción y compilación de un kérnel Linux a medida

Cómo quitar módulos y compilar un kérnel GNU/Linux.

La compilación de un kérnel GNU/Linux es una práctica poco habitual respecto a hace una década. Hoy en día, apenas se realiza una recompilación del kernel y, cuando se hace, es para soportar un nuevo hardware no incluido en el kérnel de la distribución o bien por puro interés en aprender a realizar esta técnica. También se realiza para el uso en sistemas embebidos o dispositivos empotrados como puede ser Raspberry Pi o smartphones.

Esta entrada busca como fin la optimización y reducción de tamaño del kérnel utilizado por Debian Jessie, desintegrando los módulos no necesarios en dicho núcleo y rechazando el uso de otro tipo de funcionalidades como conexiones inalámbricas o puertos USB.



Partiendo de cero

Tux, la mascota de Linux.Para hacer una compilación del kérnel necesitamos los ficheros fuente del núcleo. Uno de los primeros pasos conocer qué kérnel estamos utilizando en nuestro sistema para poder descargarnos los ficheros fuente. La orden uname -r nos indica que el núcleo utilizado por nuestro Debian Jessie en nuestro caso es el 3.16.0-4-amd64.

Este se puede instalar con apt-get install linux-source-X.X, siendo el resultado un fichero comprimido ubicado en /usr/src/linux-source-X.X.tar.xz o bien a través del sitio web kernel.org, donde aparece como última versión estable la 4.8 en estos momentos.

Continuamos creando un directorio donde ubicar los archivos del núcleo y realizar la compilación. Para ello ejecutamos mkdir ~/Kernel y dentro de él ejecutamos tar xf /usr/src/linux-source-3.16.tar.xz.

Copiando la configuración del kérnel actual

Para agilizar y afinar el proceso de configuración de la nueva compilación, tomamos como punto de partida la configuración del núcleo actual. Esta configuración la copiamos con cp /boot/config-uname -r /home/nano/Kernel/linux-source-3.16/.config Si tenemos únicamente un núcleo instalado en nuestro sistema, no es necesario hacer uso de uname -r.

Compresión y compilación del kérnel de Linux.

Primeros pasos y creación del entorno de trabajo.

Es necesario etiquetar el nuevo núcleo desde la constante EXTRAVERSION del fichero Makefile, ubicado dentro del directorio descomprimido. Un ejemplo sería comenzar con -01 e ir incrementando conforme vayamos realizando nuevas compilaciones, pues nuestro objetivo final es obtener un núcleo muy básico a la vez que funcional.

Por defecto, el núcleo de Linux incluye soporte para todos los dispositivos de hardware. El comando make localmodconfig permite configurar la nueva compilación con los dispositivos hardware de nuestra máquina.

Configuración con make localmodconfig.

Comando make localmodconfig, que configura los módulos conforme al hardware de nuestra máquina.

Compilando un nuevo kérnel de Linux

Compilar un núcleo es un proceso que requiere de la capacidad de cómputo de nuestro procesador. Por ello, mientras mayor sea la capacidad del procesador y menor sea el tamaño de la compilación, menor será el tiempo de espera. En mi caso pasó de compilar en seis minutos a no llegar a los dos minutos.

En 1990, compilar el primer kérnel le llevó a Linus Torvalds unos 12 minutos. Aunque el tamaño de este núcleo era muchísimo menor que el actual. En 2010 confirmaba que su sistema podía llegar a hacerlo en apenas un minuto.

En Debian, podemos conocer el número de cores de nuestro procesador con la instrucción grep processor /proc/cpuinfo | wc -l para aprovechar al máximo su capacidad y reducir el tiempo de compilación.

El resultado de la nueva compilación de nuestro kérnel lo guardaremos en un un paquete .deb. En mi caso, ejecutaré el comando make -j8 INSTALL_MOD_STRIP=1 deb-pkg. Establecer el parámetro INSTALL_MOD_STRIP a 1 eliminará los símbolos propios de debug, reduciendo el tamaño del paquete generado.

Podemos conocer el tiempo que tarda en finalizar esta tarea anteponiéndole time

En un principio, la compilación original y con los símbolos debug ocupaba 33MB y había tomado un total de 23 minutos. Mientras que la compilación ejecutada con la configuración de nuestro hardware y el parámetro INSTALL_MOD_STRIP activado pasa a ser un paquete de 6,6MB y 6 minutos de compilación.

Configuración a través de una herramienta gráfica

Desde el archivo .config copiado anteriormente es posible establecer la configuración de la compilación. Aún así, es un proceso enfarragoso que puede llevar a muchos errores, pues hay módulos que depende de otros módulos. Para agilizar esta tarea, existen herramientas gráficas que ayudan a modificar las opciones y módulos a compilar. Por un lado está menuconfig, que lo hace a través de una consola gráfica y por otro GConf y xconfig que utilizan el entorno de escritorio.

Antes de compilar nuevamente (en caso de que lo hayamos hecho) es recomendable eliminar los paquetes antiguos ejecutando rm ../* dentro del directorio que en el trabajamos (linux-source-3.16 en mi caso). Igualmente, ejecutamos make clean que mantiene el fichero de configuración previo y cambiamos el EXTRAVERSION del fichero Makefile.

A continuación, utilizaremos xconfig para la configuración de los módulos a compilar. xconfig utiliza las librerías de desarrollo Qt3 (qt3-dev-tools) y se ejecuta con make xconfig

Interfaz gráfica de xconfig.

Este es xconfig, una interfaz gráfica para configurar la compilación del kérnel.

Instalando el kérnel compilado

El núcleo compilado se instala como cualquier paquete .deb dpkg -i ../linux-image-3.16.36-01_3.16.36-01-1_amd64.deb Esto desempaquetará, instalará, actualizará el initramfs y generará una nueva configuración de GRUB, añadiendo una nueva entrada.

Tras reiniciar, accedemos a la opción «Opciones avanzadas para Debian GNU/Linux» donde podremos elegir el sistema operativo Debian Jessie con el núcleo 3.16.36-01. Si el arranque se produce correctamente podemos comprobar nuestro núcleo con la ejecución de uname -r en una terminal de comandos.

En caso de que la compilación sea fallida y no cargue, debemos iniciar con el núcleo de siempre, eliminando igualmente los paquetes .deb generados y ejecutando en esta ocasión make mrproper para partir de una base aún más limpia (sin el .config utilizado). También deberemos desinstalar este kérnel de nuestro sistema.

Eliminando y desinstalando una versión del kérnel Linux

Si hemos realizado una compilación que hace que no arranca en nuestro sistema o que simplemente no usamos, podemos desinstalarla para liberar espacio y que no aparezca en el gestor arranque GRUB.

Con superusuario, ejecutamos dpkg -l | grep linux-image para ver los kérnels instalados en nuestro sistema. Mientras que con apt-get remove --purge linux-image-X.X.X-X desinstalamos el kérnel que no funciona correctamente, como en este caso ha sido el linux-image-3.16.36-04. Nuevamente se actualizará el initramfs y las entradas del GRUB.

Desinstalación de un kérnel mal compilado.

Desinstalar y eliminar kérnel o núcleo en Debian Jessie.

Recuerda eliminar el paquete .deb generado y ejecutar make clean para volver a activar aquellos módulos que crees que fallan o make mrproper para poder partir desde cero, eliminando también el archivo .config.

Versionado del kérnel

Como resultado final, os dejo una tabla con las modificaciones progresivas que he ido realizando. Pasé de un paquete de 33MB a un paquete de 2,8MB, mientras que vmlinuz pasó de 3,1MB a 1,8MB. En esta tabla encontráis todos los módulos restados al kérnel de Linux tras la ejecución del comando make localmodconfig y su correspondiente reducción de tamaño.

# Módulos .deb vmlinuz
01 Optimize for size (CC_OPTIMIZE_FOR_SIZE), High Resolution Timer Support (HIGH_RES_TIMERS), Linux guest support (HYPERVISOR_GUEST), Network packet filtering framework (Netfilter) (NETFILTER), QoS and/or fair queueing (NET_SCHED), Bluetooth subsystem support (BT), BF switch subsystem support (RFKILL), Parallel port support (PARPORT), Macintosh device drivers (MACINTOSH_DRIVERS), Wireless LAN (WLAN), Wan interfaces support (WAN), Hardware Monitoring support (HWMON), Multimedia support (MEDIA_SUPPORT), Sound card support (SOUND), Hardware crypto devices (CRYPTO_HW), Virtualization (VIRTUALIZATION) 5MB 2,6MB
02 Resource counters (RESOURCE_COUNTERS), DMA memory allocation support (ZONE_DMA), Symmetric multi-processing support (SMP), Memtest (MEMTEST), Enable DMI scanning (DMI), IBM Calgary IOMMU support (CALGARY_IOMMU), Enable support for 16-bit segments (X86_16BIT), Allow for memory hot-add (MEMORY_HOTPLUG), Track memory changes (MEM_SOFT_DIRTY), x86 architectural random number generator (ARCH_RANDOM), AC Adapter (ACPI_AC), Battery (ACPI_BATTERY), The IPv6 protocol (IPV6), Amateur Radio support (HAMRADIO), Wireless (WIRELESS) 4,3MB 2,3MB
03 AMD MCE features (X86_MCE_AMD), Supervisor Mode Access Prevention (X86_SMAP), IP: multicast routing (IP_MROUTE), USB Gadget Support (USB_GADGET), LED Trigger support (LEDS_TRIGGERS), Accessibility support (ACCESSIBILITY), Virtualization drivers (VIRT_DRIVERS), Staging drivers (STAGING), Platform support for Chrome hardware (CHROME_PLATFORMS), Network File Systems (NETWORK_FILESYSTEMS) 4MB 2,2MB
04 Support for paging of anonymous memory (swap) (SWAP), Enable the block layer (BLOCK), Enable VM86 support (VM86), Namespaces support (NAMESPACES), Processor (ACPI_PROCESSOR), Extended Error Log support (ACPI_EXTLOG), Support for PCI Hotplug (HOTPLUG_PCI), ACPI Platform Error Interface (APEI) (ACPI_APEI), /dev/agpgart (AGP Support) (AGP), 09ACPI (Advanced Configuration and Power Interface) Support (ACPI), SCSI low-level drivers (SCSI_LOWLEVEL) 3,6MB 2,0MB
05 Fusion MPT device support (FUSION), Fibre Channel driver support (NET_FC), BSD Process Accounting (BSD_PROCESS_ACCT), Export task/process statistics through netlink (TASKSTATS) 3,6MB 1,9MB
06 SFI (Simple Firmware Interface) Support (SFI), CPU Frequency scaling (CPU_FREQ), CPU idle PM support (CPU_IDLE), ISDN support (ISDN), Watchdog Timer Support (WATCHDOG), Intel 8xx/9xx/G3x/G4x/HD Graphics (DRM_I915), GPIO Support (GPIOLIB), Power supply class support (POWER_SUPPLY) 3,2MB 1,9MB
07 Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) (DRM), Support for frame buffer devices (FB), Backlight & LCD device support (BACKLIGHT_LCD_SUPPORT), USB support (USB_SUPPORT), Machine Check / overheating reporting (X86_MCE), System V IPC (SYSVIPC), POSIX Message Queues (POSIX_MQUEUE), Enable process_vm_readv/writev syscalls (CROSS_MEMORY_ATTACH), Enable system-call auditing support (AUDITSYSCALL), Enable VM event counters for /proc/vmstat (VM_EVENT_COUNTERS), Profiling support (PROFILING) 2,9MB 1,9MB
08 Checkpoint/restore support (CHECKPOINT_RESTORE), IP: multicast routing (IP_MROUTE), FDDI driver support (FDDI), HIPPI driver support (HIPPI), Joystick interface (INPUT_JOYDEV), Joysticks/Gamepads (INPUT_JOYSTICK), Tablets (INPUT_TABLET), Touchscreens (INPUT_TOUCHSCREEN), Miscellaneous devices (INPUT_MISC), Mice (INPUT_MOUSE), Mouse interface (INPUT_MOUSEDEV), DM uevents (DM_UEVENT), Debug memory initialisation (DEBUG_MEMORY_INIT), Compile the kérnel with debug info (DEBUG_INFO), Native language support (NLS), Miscellaneous filesystems (MISC_FILESYSTEMS), RISCiX partition support (ACORN_PARTITION_RISCIX), NSA SELinux AVC Statistics (SECURITY_SELINUX_AVC_STATS), NSA SELinux Development Support (SECURITY_SELINUX_DEVELOP), Extended 8250/16550 serial driver options (SERIAL_8250_EXTENDED), LED Support (NEW_LEDS), EDAC (Error Detection And Correction) reporting (EDAC), Real Time Clock (RTC_CLASS) 2,8MB 1,8MB
09 VGA Arbitration (VGA_ARB), Generic Thermal sysfs driver (THERMAL), VGA text console (VGA_CONSOLE), Enable full-sized data structures for core (BASE_FULL), CCM support (CRYPTO_CCM), CTR support (CRYPTO_CTR), ECB support (CRYPTO_ECB), NSA SELinux Support (SECURITY_SELINUX), AppArmor support (SECURITY_APPARMOR), TOMOYO Linux Support (SECURITY_TOMOYO), SHA1 digest algorithm (CRYPTO_SHA1), SHA224 and SHA256 digest algorithm (CRYPTO_SHA256), AES cipher algorithms (AES-NI) (CRYPTO_AES_NI_INTEL), ARC4 cipher algorithm (CRYPTO_ARC4), Enable dynamic printk() support (DYNAMIC_DEBUG), Enable suppor for printk (PRINTK), Print quota warnings to console (OBSOLETE) (PRINT_QUOTA_WARNING), Quota support (QUOTA), Report quota messages through netlink interface (QUOTA_NETLINK_INTERFACE) 2,4MB 2,0MB
10 Enable loadable module support (MODULES) 2,3MB 2,0MB

Referencias

Compartir es agradecer. Si te ha gustado... ¡compartélo!
Comparte con tus amigos










Enviar

2 Respuestas

  1. Luis dice:

    Muy bien explicado, pero ¿que beneficio hay en acortarle el tamaño al kernel?

    • Evaristo GZ dice:

      ¡Hola Luis!

      Como explico brevemente en la intro, realmente es una práctica poco habitual y que no aporta ningún beneficio al usuario común. Mucho menos en relación esfuerzo -> resultado.

      El kernel incluye soporte para que funcione (al menos lo básico) en cualquier equipo y con pequeñas excepciones en equipos muy nuevos (como el caso de portátiles) en el que puede ser que algún hardware no incluya soporte. Éste se carga en memoria con módulos que ni siquiera utilizará tu equipo, ocupando espacio en memoria. Así que esto suponía un problema en algunos equipos de hace años, pues las limitaciones en memoria RAM eran evidentes.

      A día de hoy la carga que supone a equipos modernos es ridícula. Aún así, como comento, hay quien reduce el tamaño del kernel para optimizar su uso en dispositivos ARM como las Raspberry Pi o smartphones.

      También existen personas que, aunque no reducen el tamaño del kernel, lo recompilan incluyendo los módulos que utiliza su hardware nuevo. Esto daría como resultado un kernel híbrido.

      Espero que te haya servido 🙂

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.