7.4. Manejo de dispositivos y módulos en un sistema LFS

En el Capítulo 6 se instaló el paquete Udev. Antes de entrar en detalles sobre cómo funciona, repasaremos los anteriores métodos de manejo de dispositivos.

Tradicionalmente, los sistemas Linux en general utilizan un método estático de creación de dispositivos, implicando que un gran número de nodos de dispositivo son creados en /dev (literalmente, cientos de nodos) sin tener en cuenta si el dispositivo hardware correspondiente existe en realidad. Esto se hace típicamente mediante un guión MAKEDEV, que contiene una serie de llamadas al programa mknod con los números mayor y menor correspondientes a cada posible dispositivo que pudiera existir en el mundo.

Con el uso del método Udev, sólo se crearán los nodos correspondientes a aquellos dispositivos detectados por el núcleo. Debido a que estos nodos de dispositivo se crearán cada vez que se inicie el sistema, se almacenarán en un sistema de ficheros tmpfs (el cual existe por completo en memoria). Los nodos de dispositivo no necesitan mucho espacio, por lo que la memoria utilizada es muy poca.

7.4.1. Historia

En Febrero de 2000, un nuevo sistema de ficheros llamado devfs fue incluido en los núcleos 2.3.46 y estuvo disponible en la serie 2.4 de los núcleos estables. Aunque estaba presente en las propias fuentes del núcleo, este método de creación dinámica de dispositivos nunca recibió mucho apoyo por parte del equipo de desarrolladores del núcleo.

El principal problema con el sistema adoptado por devfs era el modo en el que manejaba la detección, creación y denominación de dispositivos. El último punto, la denominación de los nodos, fue quizás el más crítico. Está generalmente aceptado que si los nombres de dispositivos son configurables, entonces las políticas de denominación deberían ser establecidas por un administrador del sistema y no impuestas por un desarrollador en particular. El sistema de ficheros devfs sufre también de extraños comportamientos inherentes a su diseño y que no pueden corregirse sin una revisión sustancial del núcleo. Durante un tiempo fué marcado como descartado debido a la falta de mantenimiento, siendo removido finalmente del núcleo en Junio de 2006.

Con el desarrollo del árbol inestable 2.5 del núcleo, posteriormente liberado como núcleos estables de la serie 2.6, aparece un nuevo sistema de ficheros virtual llamado sysfs. El trabajo de sysfs es exportar una visión de la configuración hardware del sistema a los procesos de usuario. Con esta representación visible a nivel de usuario, la posibilidad de encontrar un sustituto para devfs a nivel de usuario se hace mucho más real.

7.4.2. Implementación de Udev

7.4.2.1. Sysfs

Arriba se mencionó brevemente el sistema de ficheros sysfs. Uno podría preguntarse cómo conoce sysfs los dispositivos presentes en el sistema y qué números de dispositivo debe usar. Los crontroladores que se han compilado directamente dentro del núcleo registran sus objetos en sysfs a medida que son detectados por el núcleo. Para los controladores compilados como módulos, esto sucederá cuando se cargue el módulo. Una vez montado el sistema de ficheros sysfs (en /sys), los datos registrados en sysfs por los controladores están disponibles para los procesos de usuario y para que udevd cree los nodos de dispositivo.

7.4.2.2. Guión de inicio de Udev

El guión de inicio S10udev se ocupa de la creación de dichos nodos de dispositivo cuando se inicia Linux. Este guión desactiva /sbin/hotplug como manejador uevent. Esto se hace debido a que el núcleo ya no necesita llamar a binarios externos. En su lugar, udevd escuchará en un conector de red los uevent que el núcleo genere. A continuación, el guión de arranque copia los nodos de dispositivo estáticos que encuentre en /lib/udev/devices a /dev. Esto es necesario ya que algunos dispositivos, directorios y enlaces simbólicos son requeridos antes de que el proceso de manejo dinámico de dispositivos esté disponible durante las primeras fases del arranque del sistema. La creación de nodos de dispositivo estáticos en /lib/udev/devices proporciona también una solución para aquellos dispositivos no soportados por la infraestructura de manejo dinámico de dispositivos. Entonces el guión de arranque iniciará el demonio Udev, udevd, que actuará sobre cualquier uevent recibido. Por último, el guión de arranque fuerza al núcleo a repetir los uevents de los dispositivos que ya hayan sido registrados y espera a que udevd los maneje.

7.4.2.3. Creación de nodos de dispositivo

Para obtener los números mayor y menor correctos de un dispositivo, Udev utiliza la información proporcionada por sysfs en /sys. Por ejemplo, /sys/class/tty/vcs/dev contiene la cadena “7:0”. Esta cadena es usada por udevd para crear un nodo de dispositivo con número mayor 7 y menor 0. Los permisos y modos de los nodos creados en el directorio /dev son determinados por las reglas especificadas en los ficheros que hay en el directorio /etc/udev/rules.d/. Estas se encuentran numeradas en un formato similar al del paquete LFS-Bootscripts. Si udevd no puede encontrar una regla para el dispositivo que está creando, utilizará los permisos 660 y como propietario root:root.La documentación sobre la sintaxis de los ficheros de reglas de configuración de Udev se encuentra en /usr/share/doc/udev-113/index.html

7.4.2.4. Manejo de módulos

Los controladores de dispositivos compilados como módulos pueden tener alias dentro de ellos. Los alias son visibles en la salida del programa modinfo y normalmente están relacionados con el identificados específico del bus de los dispositivos soportados por el módulo. Por ejemplo, el controlador snd-fm801 soporta dispositivos PCI con ID de vendedor 0x1319 e ID de dispositivo 0x0801, y tiene el alias “pci:v00001319d00000801sv*sd*bc04sc01i*”. Para muchos dispositivos, el controlador del bus exporta a través de sysfs el alias del controlador que podría manejar el dispositivo. Por ejemplo, el fichero /sys/bus/pci/devices/0000:00:0d.0/modalias podría contener la cadena “pci:v00001319d00000801sv00001319sd00001319bc04sc01i00”. Las reglas instaladas por LFS harán que udevd llame a /sbin/modprobe con el contenido de la variable de entorno uevent MODALIAS (que debería ser igual al contenido del fichero modalias del sysfs), cargando todos los módulos cuyos alias concuerden con dicha cadena tras la expansión de comodines.

En el ejemplo, esto significa que en adición a snd-fm801, el obsoleto (y no deseado) controlador forte será cargado si está disponible. Más abajo se muestran formas de evitar la carga de dispositivos no deseados.

El propio núcleo también es capaz de cargar módulos para protocolos de red, sistemas de ficheros y soporte NLS bajo demanda.

7.4.2.5. Manejo de dispositivos dinámicos/conectables en caliente

Cuando conectas un dispositivo, como un reproductor MP3 por USB, el núcleo reconoce que el dispositivo está conectado ahora y genera un uevent. Este uevent es manejado por udevd como se describe arriba.

7.4.3. Problemas con la carga de módulos y la creación de dispositivos

Hay algunos problemas en relación con la creación automática de nodos de dispositivos.

7.4.3.1. Un módulo del núcleo no se carga automáticamente

Udev cargará un módulo sólo si este tiene un alias específico del bus y el controlador del bus exporta correctamente los alias necesarios a sysfs. En caso contrario, la carga del módulo deberá realizarse por otros métodos. Con Linux-2.6.22.6, se sabe que Udev carga los controladores correctamente escritos para dispositivos INPUT, IDE, PCI, USB, SCSI, SERIO y FireWire.

Para determinar si el controlador de dispositivo que necesitas tiene el soporte necesario para Udev, ejecuta modinfo con el nombre del módulo como argumento. Ahora intenta localizar el directorio del dispositivo bajo /sys/bus y comprueba si hay un fichero modalias.

Si el fichero modalias existe en sysfs, el controlador soporta el dispositivo y puede hablar con él directamente, pero no contiene el alias, esto es un fallo en el controlador. Carga el controlador sin la ayuda de Udev y espera que el problema sea solucionado más adelante.

Si no hay un fichero modalias en el directorio correspondiente bajo /sys/bus, esto significa que los desarrolladores del núcleo no han añadido todavía soporte de alias a ese tipo de bus. Con Linux-2.6.22.6, este es el caso con los bus ISA. Se espera que esto se resuelva e futuras versiones del núcleo.

Udev no está pensado para cargar controladores “envoltorio”, como snd-pcm-oss o controladores que no pertenecen al hardware, como loop.

7.4.3.2. Un módulo del núcleo no se carga automáticamente y Udev no intenta cargarlo

Si el módulo “envoltorio” sólo amplía la funcionalidad proporcionada por otro módulo (del modo que snd-pcm-oss amplía la funcionalidad de snd-pcm haciendo que las tarjetas de sonido están disponibles para aplicaciones OSS), configura modprobe para cargar el envoltorio despues de que Udev carge el módulo envuelto. Para hacer esto, añade una línea “install” en /etc/modprobe.conf. Por ejemplo:

install snd-pcm /sbin/modprobe -i snd-pcm ; \
    /sbin/modprobe snd-pcm-oss ; true

Si el módulo en cuentión no es un envoltorio y es útil por si mismo. configura el guión de arranque S05modules para cargar dicho módulo en el arranque del sistema. Para hacer esto, añade una nueva línea con el nombre del módulo al fichero /etc/sysconfig/modules. Esto también funciona para módulos envoltorio, pero no es óptimo en dicho caso.

7.4.3.3. Udev carga módulos no deseados

Entonces no construyas el módulo, o ignoralo en el fichero /etc/modprobe.conf como se hace en el siguiente ejemplo para el módulo forte:

blacklist forte

Los módulos ignorados aún pueden cargarse manualmente usando el comando modprobe.

7.4.3.4. Udev crea un dispositivo incorrectamente, o hace un enlace simbólico erroneo

Esto sucede normalmento cuando una regla concuerda inesperadamente con un dispositivo. Poe ejemplo, una regla pobremente escrita puede coincidir, en cuanto al vendedor, tanto con un disco SCSI (como se desea) como con el correspondiente dispositivo SCSI genérico (incorrecto). Encuentra la regla erronea y hazla más específica.

7.4.3.5. Udev no crea un dispositivo

Se asume que el controlador ha sido compilado estáticamente dentro del núcleo o que ya ha sido cargado como módulo, y que ya has comprobado que Udev no crea un dispositivo equivocado.

Udev no tiene la información necesaria para crear un nodo de dispositivo si un controlador del núcleo no exporata sus datos a sysfs. Este es el caso más común con controladores externos al árbol del núcleo. Crea un nodo de dispositivo estático en /lib/udev/devices con los números mayor/menor apropiados (mira el fichero devices.txt en la documentación del núcleo o la documentación proporcionada por el distribuidor del controlador externo). El nodo de dispositivo estático será copiado a /dev por el guión de arranque S10udev.

7.4.3.6. El orden de denominación de los dispositivos cambia aleatoriamente tras un reinicio

Esto se debe al hecho de que Udev, por diseño, maneja los uevent y la carga de módulos en paraleo, y por tanto en un orden impredecible. Esto nunca será “fijado”. No deberías confiar en que los nombres de dispositivos del núcleo sean estables. En su lugar, crea tus propias reglas para crear enlaces simbólicos con nombres estables basadas en algún atributo estable del dispositivo, como un número de serie o la salida de las diversas utilidades *_id instaladas por Udev. Mira los ejemplos en Sección 7.12, “Crear enlaces simbólicos persnalizados a los dispositivos” y Sección 7.13, “Configuración del guión network”.

7.4.4. Lectura útil

En los siguientes sitios hay documentación de ayuda adicional: