Los módulos del kernel son piezas de código, normalmente drivers o soporte para sistemas de archivos y protocolos de red, que se cargan y descargan en el kernel en marcha sin reiniciar. En este tutorial aprenderás a consultar los módulos cargados, a cargarlos y descargarlos con modprobe, a fijar sus parámetros, a cargarlos en el arranque, a bloquear los que no quieres y a compilar un módulo externo con DKMS para que se reconstruya solo con cada kernel nuevo, todo en Ubuntu 24.04.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Los comandos lsmod, modinfo y modprobe son iguales en Debian 12 y Rocky Linux 9; cambian los paquetes de DKMS y el comando para regenerar el initramfs (dracut -f en Rocky).
  • Un usuario no root con privilegios sudo.
  • Acceso a la consola del servidor (la consola VNC del panel en un VPS) por si un cambio en los módulos de red o de disco impide acceder por SSH.

Paso 1: Consultar los módulos cargados

lsmod lista los módulos cargados en este momento:

lsmod | head -5
Module                  Size  Used by
tls                   155648  0
xt_conntrack           12288  2
nf_conntrack          196608  1 xt_conntrack
ip6t_REJECT            12288  1

La columna Used by indica cuántas referencias tiene el módulo y qué otros módulos dependen de él. No podrás descargar un módulo mientras ese contador sea mayor que 0.

Para ver la información de un módulo concreto, su archivo, licencia, dependencias y parámetros, usa modinfo:

modinfo dummy
filename:       /lib/modules/6.8.0-45-generic/kernel/drivers/net/dummy.ko.zst
alias:          rtnl-link-dummy
description:    Dummy netdevice driver which discards all packets sent to it
license:        GPL
depends:
intree:         Y
name:           dummy
parm:           numdummies:Number of dummy pseudo devices (int)

Los módulos de Ubuntu 24.04 están comprimidos (.ko.zst) en /lib/modules/$(uname -r)/. Algunas funciones no son módulos sino que están compiladas dentro del kernel; modinfo también las encuentra, y la lista completa está en modules.builtin:

grep -c . /lib/modules/$(uname -r)/modules.builtin

Un módulo integrado no aparece en lsmod y no se puede descargar.

Paso 2: Cargar y descargar módulos con modprobe

Usa siempre modprobe en lugar de insmod y rmmod: resuelve dependencias automáticamente y aplica la configuración de /etc/modprobe.d/.

Como ejemplo usarás dummy, un driver de interfaces de red virtuales que no afecta a nada. Cárgalo:

sudo modprobe dummy

Comprueba que está cargado y que ha creado una interfaz:

lsmod | grep dummy
ip link show type dummy
dummy                  12288  0
5: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 3e:91:7c:08:5a:d2 brd ff:ff:ff:ff:ff:ff

Para ver qué haría modprobe sin ejecutarlo, incluidas las dependencias que cargaría, usa --show-depends:

modprobe --show-depends nf_nat

Descarga el módulo:

sudo modprobe -r dummy

Si el módulo está en uso, modprobe -r falla con Module ... is in use. Detén primero el servicio o elimina el dispositivo que lo utiliza.

Paso 3: Pasar parámetros a un módulo

Muchos módulos aceptan parámetros. modinfo -p los lista:

modinfo -p dummy
numdummies:Number of dummy pseudo devices (int)

Parámetros al cargar

Puedes pasarlos directamente a modprobe:

sudo modprobe dummy numdummies=3
ip -br link show type dummy
dummy0           DOWN           3e:91:7c:08:5a:d2 <BROADCAST,NOARP>
dummy1           DOWN           a6:12:4f:9e:03:77 <BROADCAST,NOARP>
dummy2           DOWN           d2:5b:81:6c:e4:19 <BROADCAST,NOARP>

Los parámetros solo se leen al cargar el módulo, así que para cambiarlos hay que descargarlo y volver a cargarlo:

sudo modprobe -r dummy

Parámetros persistentes

Para que se apliquen siempre que se cargue el módulo, crea un archivo en /etc/modprobe.d/ (debe terminar en .conf):

sudo nano /etc/modprobe.d/dummy.conf
options dummy numdummies=2

Carga el módulo sin parámetros y comprueba que se ha usado el valor del archivo:

sudo modprobe dummy
ip -br link show type dummy

Deberías ver dummy0 y dummy1. Muchos módulos publican el valor activo de sus parámetros en /sys/module/<módulo>/parameters/; dummy no lo hace, por eso aquí se comprueba por su efecto.

Paso 4: Cargar módulos en el arranque

El kernel carga automáticamente la mayoría de drivers cuando detecta el hardware correspondiente. Para los que no se cargan solos (por ejemplo, br_netfilter que necesitan Kubernetes y otros entornos de contenedores), añádelos a un archivo en /etc/modules-load.d/, un módulo por línea:

sudo nano /etc/modules-load.d/custom.conf
br_netfilter
dummy

El servicio systemd-modules-load lee estos archivos en cada arranque. Aplícalo ahora sin reiniciar:

sudo systemctl restart systemd-modules-load.service
lsmod | grep -E 'br_netfilter|dummy'

Cuando termines las pruebas, quita dummy de este archivo y borra /etc/modprobe.d/dummy.conf para no crear interfaces innecesarias en cada arranque.

Si falla, revisa sus mensajes:

journalctl -b -u systemd-modules-load.service

Paso 5: Bloquear un módulo

A veces quieres impedir que se cargue un módulo: un driver que da problemas, un protocolo que no usas o un dispositivo que no existe. Como ejemplo, en máquinas virtuales a menudo se carga floppy sin que haya disquetera.

La directiva blacklist impide la carga automática por detección de hardware, pero no que otro módulo o un usuario lo cargue explícitamente. Para bloquearlo del todo, añade también una regla install que lo sustituya por /bin/false:

sudo nano /etc/modprobe.d/blacklist-floppy.conf
blacklist floppy
install floppy /bin/false

Si el módulo está incluido en el initramfs, se cargaría antes de leer esta configuración. Regenera el initramfs para que incluya el archivo:

sudo update-initramfs -u

Descárgalo si está cargado y comprueba que ya no se puede cargar:

sudo modprobe -r floppy
sudo modprobe floppy

El segundo comando debe fallar con un error Error running install command '/bin/false' for module floppy, y lsmod | grep floppy no debe devolver nada.

Para deshacer el bloqueo, borra el archivo y vuelve a ejecutar sudo update-initramfs -u.

Paso 6: Compilar un módulo externo con DKMS

Los módulos que no vienen con el kernel (algunos drivers de hardware, VirtualBox, ZFS de terceros...) deben compilarse para cada versión del kernel. DKMS automatiza esto: registra el código fuente y lo recompila e instala cada vez que se instala un kernel nuevo.

Instalar DKMS

Instala DKMS, las herramientas de compilación y las cabeceras del kernel en uso:

sudo apt update
sudo apt install dkms build-essential linux-headers-$(uname -r)

Instala también el metapaquete de cabeceras para que se actualicen junto con el kernel; sin ellas, DKMS no puede compilar para un kernel nuevo:

sudo apt install linux-headers-generic

Crear un módulo de ejemplo

DKMS espera el código en /usr/src/<nombre>-<versión>. Crea un módulo mínimo llamado hello:

sudo mkdir -p /usr/src/hello-1.0
sudo nano /usr/src/hello-1.0/hello.c
#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Ejemplo de modulo gestionado con DKMS");
MODULE_VERSION("1.0");

static int __init hello_init(void)
{
    pr_info("hello: modulo cargado\n");
    return 0;
}

static void __exit hello_exit(void)
{
    pr_info("hello: modulo descargado\n");
}

module_init(hello_init);
module_exit(hello_exit);

Crea el Makefile que usa el sistema de compilación del kernel:

sudo nano /usr/src/hello-1.0/Makefile
obj-m := hello.o

Y el archivo dkms.conf, que describe el módulo a DKMS:

sudo nano /usr/src/hello-1.0/dkms.conf
PACKAGE_NAME="hello"
PACKAGE_VERSION="1.0"
BUILT_MODULE_NAME[0]="hello"
DEST_MODULE_LOCATION[0]="/updates/dkms"
MAKE[0]="make -C ${kernel_source_dir} M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build"
CLEAN="make -C ${kernel_source_dir} M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build clean"
AUTOINSTALL="yes"

AUTOINSTALL="yes" hace que DKMS lo recompile automáticamente al instalar un kernel nuevo.

Registrar, compilar e instalar

sudo dkms add -m hello -v 1.0
sudo dkms build -m hello -v 1.0
sudo dkms install -m hello -v 1.0

Comprueba el estado:

dkms status
hello/1.0, 6.8.0-45-generic, x86_64: installed

Carga el módulo y revisa su mensaje en el log del kernel:

sudo modprobe hello
sudo dmesg | tail -n 2
[ 8123.402117] hello: loading out-of-tree module taints kernel.
[ 8123.402391] hello: modulo cargado

El aviso de taints kernel es normal para cualquier módulo externo.

Mantenimiento

Para eliminar el módulo de todos los kernels y de DKMS:

sudo modprobe -r hello
sudo dkms remove hello/1.0 --all

Tras una actualización del kernel, dkms status debería mostrar el módulo como installed también para la nueva versión. Si no, revisa el log de compilación que DKMS indica en su mensaje de error.

Solución de problemas

modprobe: FATAL: Module xxx not found in directory /lib/modules/.... El módulo no existe para el kernel en uso. En Ubuntu, algunos drivers están en el paquete linux-modules-extra-$(uname -r); en imágenes cloud que usan otras variantes de kernel pueden no estar disponibles.

modprobe: ERROR: could not insert 'xxx': Key was rejected by service. Secure Boot está activo y el módulo no está firmado con una clave de confianza. Ubuntu firma los módulos DKMS con una clave MOK propia; debes registrarla con sudo mokutil --import /var/lib/shim-signed/mok/MOK.der y confirmar el registro desde la consola en el siguiente arranque.

dkms build falla con Kernel headers ... cannot be found. Faltan las cabeceras de ese kernel. Instala linux-headers-<versión> para la versión que indica el error.

El módulo bloqueado sigue cargándose tras reiniciar. Se carga desde el initramfs. Ejecuta sudo update-initramfs -u y reinicia.

Conclusión

Ahora sabes consultar, cargar y descargar módulos con modprobe, fijar sus parámetros, cargarlos en el arranque, bloquearlos y mantener un módulo externo con DKMS a través de las actualizaciones del kernel. Como siguientes pasos, puedes revisar los mensajes que generan los drivers con dmesg, explorar /sys/module/ para ver los parámetros activos o ajustar el kernel en tiempo real con sysctl.