Los módulos del kernel

El kernel de GNU/Linux es modular, lo que significa que puede extender su funcionalidad mediante el uso de módulos de kernel dinámicamente cargados. El kernel tiene dos funciones principales:

  • Controlar el acceso a los dispositivos físicos de la máquina
  • Planificar cuándo y como interactúa un proceso con dichos dispositivos.

Un módulo del kernel puede proporcionar:

  • Un driver que añade soporte para un nuevo hardware
  • Soportar un sistema de archivos como NFS o btrfs

En los sistemas más modernos, los módulos del kernel se cargan automáticamente. En cualquier caso, hay ocasiones en que es necesario cargar o desactivar módulos manualmente, como cuando se desea utilizar un módulo en lugar el que se está utilizando, o cuando un módulo se está comportando de modo anómalo.

Las herramientas para manipular los módulos del kernel, se encuentran en el paquete kmod. Por ello, antes de empezar, es necesario que instalemos dicho paquete, mediante el comando siguiente:

# yum install kmod

Listar los módulos del kernel actualmente cargados.

Para cargar los módulos del kernel actualmente cargados, es preciso ejecutar el comando lsmod

Cada una de las filas especifica:

  • El nombre del módulo del kernel cargado actualmente en memoria
  • La cantidad de memoria que utiliza
  • La suma total de procesos que están utilizando el módulo y otros módulos que dependen de él, seguido de una lista de los nombres de dichos módulos, si es que existen. Usando esta lista, se pude primero desactivar los módulos que dependen del que queremos desactivar.

Actividad 1. Muestra los módulos actualmente cargados en tu sistema.

Toma una captura del resultado, y guárdalo con el nombre Act1-hwlinux.png.

Mostrar información sobre un cierto módulo

Se puede obtener información detallada sobre un cierto módulo, con el comando modinfo

La captuar anterior muestra la información sobre el módulo e1000e, que es el driver de una interfaz de red Intel PRO/1000.

Los archivos de los módulos se encuentran en el directorio /lib/modules/versión-kernel/. Dichos archivos tienen como extensión .ko. Pero al utilizar la el comando modinfo no es necesario escribir la extensión, ya que nos estamos refiriendo al módulo en sí, y no al archivo que lo contiene.

El resultado del comando muestra, al menos, la siguiente información:

  • filename: ruta absoluta al archivo .ko que contiene el módulo. Si se usa modinfo -n solo se muestra este campo.
  • description: descripción corta del módulo. Se puede usar modinfo -d para mostrar únicamente esta información.
  • alias: el campo alias puede aparecer varias veces indicando diferentes alias del módulo. También puede no aparecer.
  • depends: este campo contiene una lista separada por comas de todos los módulos de los que depende. Su el módulo no depende de ningún otro, no se mostrará este campo
  • parm: cada campo parm es un parámetro aplicable al módulo, y se presenta en forma de nombre_parámetro:descripción. Estos parámetros se pueden usar en la línea de comandos, o bien mediante un archivo .conf en el directorio /etc/modprobe.d/

Actividad 2. Muestra los detalles de uno de los módulos que tenga tu sistema cargado.

Toma una captura y guárdala con el nombre Act2-hwlinux.png.

Carga del módulo

Para cargar un cierto módulo, usamos el comando modprobe

# modprobe wacon

Por defecto, modprobe trata de cargar un módulo desde /lib/modules/versión-kernel/drivers. En dicho directorio, cada tipo de módulo tiene su propio subdirectorio, como net/ para módulos de interfaces de red o scsi/ para drivers de dispositivos SCSI.

Algunos módulos tienen dependencias, que son otros módulos del kernel que deben ser cargados antes de que el módulo en cuestión. El comando modprobe tiene en cuenta esto, de modo que al ejecutarlo, examina las dependencias, y en caso de existir alguna, las carga previamente. Además, modprobe resuelve las dependencias recursivamente, de modo que cargará las "dependencias de las dependencias". Por ejemplo, la siguiente imagen muestra cómo durante la carga del módulo de "Fibre Channel over Ethernet" se cargan a su vez otros módulos de los que depende.

El comando insmod permite activar un módulo, aunque no resuelve dependencias. Por ello, es siempre preferible utilizar modprobe a insmod

Busca entre los módulos de que dispone tu sistema, y trata de cargar uno que no lo esté. Infórmate sobre su funcionalidad.

Toma una captura donde se pueda ver como se carga el módulo y cómo aparece entre los módulos cargados. Guárdala como Act3-hwlinux.php

Desactivación de un módulo

Para desactivar un módulo utilizamos el comando modprobe -r nombre_modulo. La desactivación de un módulo no es posible cuando:

  • Un proceso está utilizando directamente el módulo.
  • Un proceso está utilizando un módulo depende directamente del módulo que queremos desactivar.
  • Un proceso está utilizando un módulo depende indirectamente (a través del árbol de dependencias) del módulo que queremos desactivar.

¿Cómo es posible comprobar dichas dependencias? El comando modinfo nos permite hacerlo. Por ejemplo, en la siguiente captura podemos ver el árbol de dependencias del módulo firewire_ohci.

Se puede observar que crc-itu-t depende de firewire_core que a su vez depende de firewire_ohci. Para desactivar el módulo firewire_ohci podemos ejecutar como el comando modprobe -v -r firewire_ohci.

Actividad 4. Desactiva el módulo de la interfaz de red Intel Pro/1000 de tu sistema. Después trata de hacer ping a tu puerta de enlace.

Toma una captura en el momento en que desactives el modulo, y guárdal con el nombre Act4-hwlinux.png

Ajustar parámetros de un cierto módulo

Los módulos suelen soportar parámetros, que modifican su comportamiento por defecto. Si pensamos en una interfaz de red Intel 82574 (cuyo módulo se llama e1000e), existen diferentes parámetros detallados en el documento e1000e.txt. La forma de asignar un cierto parámetro a un módulo es: # modprobe nombre_driver nombre_parametro=valor(es). Por ejemplo:

# modprobe e1000e InterruptThrottleRate=3000,3000,3000

Para conocer los parámetros que soporta un cierto módulo, debemos consultar la documentación de dicho módulo.

Carga persistente de módulos

Para cargar de forma persistente un módulo durante el arranque, debemos crear un script en el directorio /etc/sysconfig/modules. Si por ejemplo, queremos forzar la carga del módulo foo durante el arranque, el archivo debería llamarse foo.modules. El script puede ser una simple llamada a modprobe, por ejemplo:

#!/bin/sh modprobe foo

El script debe ser ejecutable. Para ello, debemos ejecutar el siguiente comando:

# chmod 755 /etc/sysconfig/modules/foo.modules

Actividad 5. Busca uno de los módulos de tu sistema que no esté actualmente cargado. Después, configura el módulo para que inicie durante el arranque de forma persistente.

Toma una captura del archivo donde estableces la carga persistente del módulo.

Consultando el hardware de la máquina

GNU/Linux cuenta con diversos comandos para conocer detalles sobre el harware:

  • lscpu: obtiene información sobre el microprocesador.
  • lshw: (presente en el repositorio EPEL) lista diferentes parámetros del hardware, incluyendo CPU, memoria, disco, controladora USB, etc. Dicha información es extraida de diferentes archivos del directorio /proc.
  • lspci: lista información sobre el bus PCI, así como los dispositivos conectados al mismo, como la tarjeta VGA, controladora SATA, tarjetas ethernet, etc.
  • lsusb: proporciona información sobre los dispositivos USB conectados
  • lsblk: muestra información sobre dispositivos de bloques
  • lsscsi: muestra información sobre dispositivos SCSI

Blacklisting

Es posible bloquear un módulo para que no se cargue durante el arranque. Hay dos formas de hacer esto:

Blacklisting por el archivo blacklist.conf

Supongamos que queremos bloquear durante el arranque el módulo foo. Entonces debemos añadir la siguiente línea en el archivo /etc/modprobe.d/blacklist.conf:

blacklist foo

De este modo, Linux no cargará el módulo foo durante el siguiente reinicio.

Actividad 6. Comprueba que el módulo nfsd está cargado. Después, añade el módulo nfsd a la blacklist de los módulos. Reinicia el sistema y comprueba que ya no se carga automáticamente.

Realiza una captura donde se pueda ver el archivo de blacklisting, así como la lista de módulos cargados, donde no debe aparecer. Guárdala con el nombre Act6-hwlinux.png

Blacklisting por la configuración de arranque

En ocasiones, un módulo no responde al blacklisting explicado en el apartado anterior. Además, en ocasiones es preciso bloquear la carga de un módulo para poder arrancar el sistema. El presente procedimiento permite crear una blacklist antes de que el sistema arranque. Para utilizar este método es preciso seguir los siguientes pasos:

  1. Identificar el kernel por defecto empleado para arrancar. podemos ejecutar el comando uname -r.
  2. Editar el archivo grub.cfg, y añadir la opción modprobe.blacklist=foo,bar en la línea referente al kernel (que hemos comprobado anteriormente con uname -r) para bloquear los módulos foo y bar. Por ejemplo:
linux16 /vmlinuz-3.10.0-123.el7.x86_64 root=UUID=d6720fa1-aec4-4dab-8982-2d4a28091e46 ro vconsole.keymap=es crashkernel=auto vconsole.font=latarcyrheb-sun16 rhgb quiet modprobe.blacklist=foo, bar LANG=es_ES.UTF-8

Actividad 7. Bloquea el driver de la tarjeta de red durante el arranque, empleando el blacklisting explicado anteriormente.

Guarda una captura de tu archivo grub.cfg donde se pueda ver el blacklisting.

DMESG

dmesg es un comando que, al ser ejecutado, nos muestra en el terminal una lista con los mensajes del kernel. Los numerosos mensajes generados por el kernel que aparecen en la pantalla cuando el ordenador arranca muestran los dispositivos de hardware que el kernel detecta e indica si es capaz de cargar el módulo correspondiente para cada uno. Además de mensajes acerca del hardware, el kernel genera otros mensajes relacionados con las funciones del kernel. Cuando algo no funciona correctamente en nuestro sistema la información ofrecida por dmesg puede ser clave para solucionar el problema. La forma más simple de usar dmesg es escribir:

# dmesg

a cantidad de mensajes generada puede resultarnos excesiva. Existen varias formas de filtrar la información. Podemos usar dos opciones de dmesg llamadas facility y level. Vamos a verlo con un ejemplo: Queremos que aparezcan solamente los mensajes de error y de advertencia (warning). Para ello usaremos la opción level y facility:

  • level: indica el nivel de criticidad del mensaje. Existen diferentes niveles:
    • emerg - system is unusable
    • alert - action must be taken immediately
    • crit - critical conditions
    • err - error conditions
    • warn - warning conditions
    • notice - normal but significant condition
    • info - informational
    • debug - debug-level messages
  • facility: permite indicar la entidad que generó el mensaje. En nuestro caso, es el kernel (kern) el que nos interesa.

Así pues, podríamos ejecutar un comando como el siguiente para conocer las incidencias con el kernel:

dmesg --level=err,warn --facility=kern

o bien:

dmesg -l err,warn -f kern

Otra forma de filtrar los mensajes es usando el comando grep. Por ejemplo, queremos obtener solamente los mensajes relativos a dispositivos usb. Escribiremos:

dmesg | grep -i usb

Actividad 8. Muestra los mensajes de error y críticos generados por el kernel.

Toma una captura y guárdala con el nombre Act7-hwlinux.png.

Actividad 9. Comprueba la versión del módulo e1000e, correspondiente a la interfaz de red Intel 82574EM. Después, busca el driver para linux de la interfaz en la página de descargas de Intel. Descárgalo en tu sistema y realiza las tareas necesarias para actualizar el módulo que trae CentOS preinstalado. Asegúrate de comprobar la versión antes y después de cargar el módulo.

Toma una captura donde se pueda observar la versión del módulo, una vez que lo hayas actualizado. Guárdala con el nombre Act8-hwlinux.png

El sistema de archivos Proc

El directorio /proc contiene una jerarquía de archivos especiales que representa el estado actual del kernel, permitiendo a las aplicaciones y usuarios comprobar el estado del mismo.

Dentro del directorio /proc/, se puede encontrar información detallada sobre el hardware así como sobre los procesos en ejecución. Además, algunos de estos archivos pueden ser manipulados para comunicar cambios al kernel.

Sistema de archivos virtual

En Linux, todo se almacena como archivos. La mayoría de los usuarios están familiarizados con los dos primeros tipos de archivos de texto y binarios. Pero el directorio /proc/ contiene otro tipo de archivos llamados virtuales. Estos archivos virtuales poseen cualidades únicas. La mayoría de ellos se enumeran como cero bytes de tamaño y sin embargo, cuando se visualizan, puede contener una gran cantidad de información. Además, la mayoría de los ajustes de hora y fecha en los archivos reflejan el tiempo y fecha actuales, indicativo del hecho de que se actualizan constantemente.

Los archivos virtuales tales como /proc/interrupts , /proc/meminfo , /proc/mounts , y /proc/partitions proporcionan una vista rápida a la actualizada del hardware del sistema. Otros, como el archivo /proc/filesystems y el directorio /proc/sys/ proporcionan información de configuración del sistema y las interfaces.

Los archivos que contienen información sobre un tema similar se agrupan en directorios virtuales y subdirectorios comunes. Por ejemplo, /proc/ide/ contiene información para los dispositivos IDE. Asimismo, los directorios de procesos contienen información acerca de cada proceso que se ejecuta en el sistema.

Visualizar archivos virtuales

Al utilizar el comando cat, more o less en los archivos dentro del directorio /proc/, los usuarios pueden acceder inmediatamente a una enorme cantidad de información sobre el sistema. Por ejemplo, para mostrar el tipo de CPU que tiene un equipo, escribimos cat /proc/cpuinfo para recibir una salida similar a la siguiente:

processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 37 model name : Intel(R) Core(TM) i5 CPU M 430 @ 2.27GHz stepping : 2 microcode : 0x9 cpu MHz : 1199.000 cache size : 3072 KB physical id : 0 siblings : 4 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 11 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm ida arat dtherm tpr_shadow vnmi flexpriority ept vpid bogomips : 4521.98 [...]

Parte de la información mostrada por los archivos de /proc/ no es legible. Existen aplicaciones que permiten acceder a esta información de un modo más amigable, como lspci , free y top .

Cambiar el contenido de los archivos virtuales:

Como regla general, la mayoría de los archivos virtuales dentro del directorio / proc son de sólo lectura. Sin embargo, algunos se pueden usar para ajustar la configuración del kernel. Esto es especialmente cierto para los archivos en el subdirectorio /proc/sys/. Por ejemplo, si deseamos que un servidor GNU/Linux actue como un router, es preciso activar en el kernel la característica de reenvío de paquetes IP. Este se puede hacer del siguiente modo:

Cambios interactuando con los archivos de /proc/sys

echo 1 > /proc/sys/net/ipv4/ip_forward

Realmente no se está escribiendo un 1 en un archivo. En cambio, se está activando un bit que indica al Kernel que debe enrutar los paquetes IP que reciba que no van a dirigidos a ninguna de sus interfaces de red.

A continuación haremos una demostración de como convertir un servidor GNU/Linux en un router, modificando el sistema de archivos /proc.

Cambios utilizando del comando sysctl

El comando /sbin/sysctl se utiliza para visualizar, configurar y automatizar configuraciones del kernel en el directorio /proc/sys/. Para una visión general rápida de todas las variables configurables en /proc/sys/, escribimos el comando /sbin/sysctl -a como root. Esto crea una lista completa. A continuación se puede ver un fragmento:

abi.vsyscall32 = 1 debug.exception-trace = 1 debug.kprobes-optimization = 1 dev.cdrom.autoclose = 1 dev.cdrom.autoeject = 0 dev.cdrom.check_media = 0 dev.cdrom.debug = 0 dev.cdrom.info = CD-ROM information, Id: cdrom.c 3.20 2003/12/17 dev.cdrom.info = dev.cdrom.info = drive name: sr0 dev.cdrom.info = drive speed: 24 dev.cdrom.info = drive # of slots: 1 dev.cdrom.info = Can close tray: 1 dev.cdrom.info = Can open tray: 1 dev.cdrom.info = Can lock tray: 1 dev.cdrom.info = Can change speed: 1 dev.cdrom.info = Can select disk: 0 dev.cdrom.info = Can read multisession: 1 dev.cdrom.info = Can read MCN: 1 dev.cdrom.info = Reports media changed: 1 dev.cdrom.info = Can play audio: 1 dev.cdrom.info = Can write CD-R: 1 dev.cdrom.info = Can write CD-RW: 1 dev.cdrom.info = Can read DVD: 1 dev.cdrom.info = Can write DVD-R: 1 dev.cdrom.info = Can write DVD-RAM: 1 dev.cdrom.info = Can read MRW: 1 dev.cdrom.info = Can write MRW: 1 dev.cdrom.info = Can write RAM: 1 dev.cdrom.info = dev.cdrom.info = dev.cdrom.lock = 0 dev.hpet.max-user-freq = 64 dev.mac_hid.mouse_button2_keycode = 97 dev.mac_hid.mouse_button3_keycode = 100 [...]

Se puede apreciar que los nombres de las características aparecen separadas por puntos. Por ejemplo el archivo /proc/sys/net/ipv4/route/min_delay aparecerá en la lista como net.ipv4.route.min_delay

El comando sysctl se puede utilizar en lugar de echo para asignar valores a los archivos se puede escribir en el directorio /proc/sys. Por ejemplo, en lugar de utilizar el comando siguiente:

# echo 1> /proc/sys/kernel/sysrq

podemos utilizar este otro:

# sysctl -w kernel.sysrq="1" kernel.sysrq = 1

Para más información sobre sysrq, consultar en http://codigounix.blogspot.com.es/2011/10/linux-kernel-sysrq-and-sak-key.html.

Realizar cambios utilizando el archivo /etc/sysctl.conf

Si bien la creación rápida de valores simples en /proc/sys/ es de gran ayuda durante una sesión, este método no funciona tan bien en un sistema de producción, ya que estos valores se pierden cuando se reinicia la máquina. Para conservar las configuraciones personalizadas, se pueden añadir al archivo /etc/sysctl.conf. Dependiendo de la distribución, habrá que editar este u otros archivos similares. Por ejemplo, en CentOS, sysctl.conf nos remite al directorio /usr/lib/sysctl.d/.

Algunos archivos útiles del sistema de archivos /proc

El directorio virtual /proc/ contiene archivos útiles para conocer la arquitectura del sistema, la cantidad de memoria disponible o los dispositivos detectados.

Actividad 10. Explora el directorio /proc y averigua la información proporcionada por 3 archivos cualesquiera. Visualiza su contenido y cópialo a un archivo de texto. Después da una breve explicación de la información principal que ofrece dicho archivo.

Entrega el archivo de texto con el nombre Act10-hwlinux.txt.