11.5. Manipulation des périphériques et modules

Dans Installing Basic System Software, nous avons installé le paquet Udev comme composant de systemd. Avant d'entrer dans les détails concernant son fonctionnement, un bref historique des méthodes précédentes de gestion des périphériques est nécessaire.

11.5.1. History

11.5.1.1. Nœuds de périphériques statiques

Traditionnellement, les systèmes Linux utilisaient une méthode de création de périphériques statiques avec laquelle un grand nombre de nœuds de périphériques étaient créés sous /dev (quelques fois littéralement des milliers de nœuds), que le matériel correspondant existait ou non. Ceci était fait le plus souvent avec un script MAKEDEV, qui contient des appels au programme mknod avec les numéros de périphériques majeurs et mineurs pour chaque périphérique possible qui pourrait exister dans le monde.

11.5.1.2. Devfs

En février 2000, un nouveau système de fichiers appelé devfs, qui créait dynamiquement des nœuds de périphérique lorsque des périphériques étaient trouvés par le noyau, a été intégré au noyau 2.3.46 et rendu disponible pour la série 2.4 des noyaux stables. Bien qu'il soit présent dans les sources du noyau, cette méthode de création dynamique des périphériques n'a jamais reçu un support inconditionnel des développeurs du noyau.

Le principal problème de l'approche adopté par devfs était la façon dont il gérait la détection, la création et le nommage des périphériques. Ce dernier problème, le nommage des périphériques, était peut-être le plus critique. Il est généralement accepté que s'il est possible de configurer les noms des périphériques, alors la politique de nommage des périphériques revient à l'administrateur du système, et non imposée par quelque développeur. Le système de fichiers devfs souffrait aussi de restrictions particulières inhérentes à sa conception et qui ne pouvaient être corrigées sans une revue importante du noyau. Il a aussi été marqué comme obsolète avec la publication de la série 2.6 et supprimé complètement avec la version 2.6.18.

11.5.1.3. Sysfs

Avec le développement de la branche instable 2.5 du noyau, sortie ensuite avec la série 2.6 des noyaux stables, un nouveau système de fichiers virtuel appelé sysfs est arrivé. Le rôle de sysfs est d'exporter une vue de la configuration matérielle du système pour les processus en espace utilisateur. Les pilotes qui sont compilés dans le noyau enregistrent directement leurs objets avec sysfs lorsqu'ils sont détectés par le noyau. Pour les pilotes compilés en modules, cette enregistrement a lieu au chargement du module. Une fois que le système de fichiers sysfs est monté (sur /sys), les données enregistrés par les pilotes avec sysfs sont visibles pour les processus en espace utilisateur. Avec cette représentation visible en espace utilisateur, la possibilité de développer un remplacement en espace utilisateur de devfs est devenu beaucoup plus réaliste.

11.5.1.4. Implémentation d'Udev

Peu de temps après l'introduction de sysfs, le travail a commencé sur un programme appelé Udev pour en profiter. Le démon udev appelait mknod() pour créer des nœuds de périphériques dans /dev dynamiquement, en fonction des informations de sysfs dans /sys. Par exemple, /sys/class/tty/vcs/dev contient la chaîne « 7:0 ». Cette chaîne était utilisée par udev pour créer un nœud de périphérique avec le nombre majeur 7 et mineur 0.

Le noyau 2.6.32 a introduit un nouveau système de fichiers virtuel nommé devtmpfs, une version améliorée de devfs. Cela permet aux nœuds de périphériques une fois de plus d'être créés dynamiquement par le noyau, sans les nombreux problèmes de devfs. Dans sa version 176, Udev ne crée plus lui-même les nœuds de périphériques, et délègue plutôt la tâche à devtmpfs.

11.5.1.5. Systemd et Eudev

En 2010, le développement de systemd a démarré, une implémentation alternative d'init. À partir d'Udev 183, l'arborescence des sources d'Udev a été fusionnée avec celle de systemd. Plusieurs développeurs de Gentoo qui n'étaient pas d'accord avec cette fusion ont annoncés un fork du projet appelé Eudev en décembre 2012, créé en extrayant le code d'Udev de systemd. Un des but d'Eudev est de permettre une meilleure installation et utilisation de udevd sans avoir besoin du reste de systemd.

11.5.2. Création de nœuds de périphérique

Par défaut, les nœuds de périphériques créés par le noyau dans un devtmpfs appartiennent à root:root et ont les permissions 600. udevd peut modifier l'appartenance et les permissions des nœuds dans le répertoire /dev et peut aussi créer des liens supplémentaires, en fonction de règles spécifiées dans les fichiers de /etc/udev/rules.d, /lib/udev/rules.d et /run/udev/rules.d. Les noms de ces fichiers commencent par un nombre, pour indiquer l'ordre dans lequel ils doivent être lancés, et ils ont une extension .rules (udevd ignorera les fichiers avec une autre extension). Tous ces fichiers de règles de ces répertoires sont combinés en une liste unique, triés par nom de fichiers, et lancés dans cette ordre. En cas de conflit, où un fichier de règle avec le même nom existe dans deux ou plus de ces répertoires, les règles dans /etc sont prioritaires, puis les fichiers de règles dans /run et enfin /lib. Tout périphérique pour qui une règle est introuvable sera simplement ignoré par udevd et laissé avec les valeurs par défaut définies par le noyau, comme décrit ci-dessus. Pour plus de détails sur l'écriture de règles Udev, voir /usr/share/doc/systemd-233/udev.html.

11.5.3. Chargement d'un module

Les pilotes de périphériques compilés en tant que modules peuvent avoir des alias. Les alias sont visibles dans la sortie du programme modinfo et sont souvent liés aux identifiants de bus des périphériques supportés par un module. Par exemple, le pilote snd-fm801 supporte les périphériques PCI avec l'ID de fabricant 0x1319 et l'ID de matériel 0x0801, et a un alias de « pci:v00001319d00000801sv*sd*bc05sc01i* ». Pour la plupart des périphériques, le pilote de bus exporte l'alias d'un pilote que pourrait gérer le périphérique via sysfs. Par exemple, le fichier /sys/bus/pci/devices/0000:00:0d.0/modalias contient la chaîne « pci:v00001319d00000801sv00001319sd00001319bc04sc01i00 ». Les règles par défaut fournies par Udev font qu'udevd appellera /sbin/modprobe avec le contenu de la variable d'environnemnt MODALIAS d'uevent (qui devrait contenir la même chose que le fichier modalias dans sysfs), ce qui fait qu'il chargera les modules dont les alias correspondent à cette chaîne après l'expansion de l'astérisque.

Dans cet exemple, cela signifie que, en plus de snd-fm801, le pilote obsolète (et indésirable) forte sera chargé s'il est disponible. Voyez plus bas pour des manières d'éviter le chargement de modules indésirables.

Le noyau lui-même peut charger des modules pour les protocoles réseau, les systèmes de fichiers et le support NLS à la demande.

11.5.4. Problèmes avec le chargement de modules et la création de périphériques

Il y peut y avoir quelques problèmes concernant la création de périphériques automatique.

11.5.4.1. Un module du noyau n'est pas chargé automatiquement

Udev ne chargera un module que s'il a un alias spécifique au bus et que le pilote de bus exporte correctement les alias nécessaires dans sysfs. Si ce n'est pas le cas, on peut charger les modules autrement. Avec Linux-4.9.21, Udev est connu pour charger les pilotes bien écrits pour les périphériques INPUT, IDE, PCI, SCSI, SERIO et FireWire.

Pour déterminer si un pilote de périphérique dont vous avez besoin a le support nécessaire pour Udev, lancez modinfo avec le nom du module en argument. Maintenant essayez de trouver le répertoire du périphérique dans /sys/bus et vérifiez s'il y a un fichier modalias.

Si le fichier modalias existe dans sysfs, que le pilote support le périphérique et peut lui parler directement, mais n'a pas l'alias, c'est un bogue du pilote. Chargez le pilote sans l'aide d'Udev et attendez que le problème soit corrigé.

S'il n'y a pas de fichier modalias dans le répertoire pertinent de /sys/bus, cela signifie que les développeurs du noyau n'ont pas encore ajouté le support de modalias dans ce type de bus. Avec Linux-4.9.21, cela est le cas pour les bus ISA. Attendez que le problème soit corrigé dans une future version du noyau.

Udev n'est pas prévu pour charger des pilotes « enveloppes » comme snd-pcm-oss et les pilotes pour des périphériques virtuels comme loop.

11.5.4.2. Un module du noyau n'est pas chargé automatiquement et Udev n'est pas prévu pour le charger

Si le module « enveloppe » ne fait qu'améliorer les fonctionnalités fournies par d'autres modules (par exemple snd-pcm-oss améliore les fonctionnalités de snd-pcm en rendant les cartes sons compatibles avec les applications OSS), configurez modprobe pour charger l'enveloppe après qu'Udev charge le module enveloppé. Pour cela, ajoutez une ligne « install » dans un fichier dans /etc/modprobe.d. Par exemple :

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

Si le module en question n'est pas une enveloppe et est utilisé seul, configurez le script de démarrage S05modules pour charger ce module au démarrage du système. Pour cela, ajoutez le nom du module dans le fichier /etc/sysconfig/modules sur une ligne séparée. Cela fonctionne pour les modules enveloppes aussi, mais est sous-optimal pour ce cas.

11.5.4.3. Udev charge certains modules indésirables

La solution est soit de ne pas construire le module, soit de le blacklister dans /etc/modprobe.d comme pour le module forte dans l'exemple suivant :

blacklist forte

Les modules blacklistés peuvent toujours être chargés manuellement avec la commande modprobe explicite.

11.5.4.4. Udev crée un mauvais lien symbolique

Cela arrive en général si une règle correspond à un appareil inattendu. Par exemple, une règle mal écrite peut correspondre à un disque SCSI (comme voulu) et au périphérique SCSI générique correspondant (incorrectement) par fabriquant. Trouvez la règle incriminée et rendez-la plus spécifique, à l'aide de udevadm info.

11.5.4.5. Les règles Udev marchent de manière peu fiable

Cela peut être une autre manifestation du problème précédent. Sinon, si vos règles utilisent les attributs sysfs, cela peut venir d'un problème de timing dans le noyau, qui sera corrigé plus tard. Pour l'instant, vous pouvez contourner le problème en créant une règle qui attend l'attribut sysfs utilisé et l'ajouter au fichier /etc/udev/rules.d/10-wait_for_sysfs.rules. Veuillez notifier la liste de développement CLFS si cela vous a aidé.

11.5.4.6. L'ordre des noms des périphérique est choisi aléatoirement au démarrage

Cela est dû au fait que Udev, par conception, gère les uevents et charge les modules en parallèle, et donc dans un ordre imprédictible. Cela ne sera jamais « corrigé ». Vous ne devriez pas vous fier à la stabilité des noms des périphériques du noyau. Créez plutôt vos propres règles qui créent des liens symboliques avec des noms stables basés sur des attributs stable du périphérique, comme un numéro de série ou la sortie des divers utilitaires *_id installés par Udev. Voyez Section 11.6, « Création de liens symboliques personnalisés vers les appareils » et Networking Configuration pour des exemples.

11.5.5. Lecture utile

De la documentation utile supplémentaire est disponible sur les sites suivants :