Au Chapitre 6, nous avons installé le paquet Udev. 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.
Traditionnellement, les systèmes Linux utilisent une méthode de
création de périphériques statiques avec laquelle un grand nombre de
nœuds de périphériques sont créés sous /dev
(quelque fois des milliers de nœuds),
que le matériel correspondant existe ou pas. Ceci est fait
typiquement 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.
En utilisant la méthode udev, seuls les nœuds pour le
périphériques détectés par le noyau sont créés. Comme ces nœuds
de périphériques seront créés à chaque lancement du système, ils
seront stockés dans un système de fichiers devtmpfs
(un système de fichiers virtuel qui
réside entièrement dans la mémoire du système). Les nœuds de
périphériques ne requièrent pas beaucoup d'espace, donc la mémoire
utilisée est négligeable.
En février 2000, un nouveau système de fichiers appelé devfs
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
du coup n'est imposée par aucun développeur en particulier. Le
système de fichiers devfs
souffre
aussi de restrictions particulières inhérentes à sa conception et
qui ne peuvent être corrigées sans une revue importante du noyau.
Il a aussi été marqué comme obsolète pendant une longue période
— à cause d'un manque de maintenance — et a
finalement été supprimé du noyau en juin 2006.
Avec le développement de la branche instable 2.5 du noyau, sortie
ensuite en 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. Avec cette représentation
visible en espace utilisateur, la possibilité de voir un
remplacement de l'espace utilisateur pour devfs
est devenu beaucoup plus réaliste.
Le système de fichier sysfs
a été
brièvement mentionné ci-dessus. On pourrait se demander comment
sysfs
connaît les périphériques
présents sur un système et quels numéros de périphériques
devraient être utilisés. Les pilotes qui ont été compilés
directement dans le noyau enregistrent leurs objets avec
sysfs
quand ils sont détectés par
le noyau. Pour les pilotes compilés en tant que modules, cet
enregistrement surviendra quand le module sera chargé. Une fois
que le système de fichier sysfs
est monté (sur /sys
), les données
enregistrées par les pilotes internes avec sysfs
sont disponibles pour les processus en
espace utilisateur ainsi que pour udev pour continuer (et faire
même des modifications aux nœuds de périphériques).
Le script de démarrage /etc/rc.d/init.d/udev s'occupe
de créer les nœuds de périphériques au lancement de Linux.
Le script supprime la gestion par défaut des uevents de
/sbin/hotplug,
ainsi le noyau n'a plus besoin de faire appel à un binaire
externe. À la place, udevd écoutera sur un socket
netlink les uevents que le noyau fait apparaître. Puis, le script
de démarrage copie les nœuds des périphériques statiques
qui existent dans /lib/udev/devices
vers /dev
. Ceci est nécessaire car
certains périphériques, répertoires et liens symboliques sont
requis avant que les processus de gestion du périphérique
dynamique ne soient disponibles pendant les premières étapes du
démarrage d'un système, ou sont nécessaire à udevd lui-même. La création des
nœuds statiques dans /lib/udev/devices
fournit aussi un
contournement facile pour les périphériques qui ne sont pas
supportés par l'infrastructure de gestion dynamique des
périphériques. Ensuite le script de démarrage lance le démon
Udev, udevd, qui
agira sur tous les uevents qu'il reçoit. Enfin, le script de
démarrage oblige le noyau à répéter des uevents pour chaque
périphérique qui a déjà été enregistré puis attend que
udevd les gère.
Le script de démarrage /etc/rc.d/init.d/udev_retry
s'occupe d'intercepter les événements pour les sous-systèmes dont
les règles se basent sur des systèmes de fichiers non montés
jusqu'à ce que le script mountfs se lance (en
particulier, il se peut que /usr et /var provoquent cela). Ce
script se lance après le script mountfs, pour que ces règles
réussissent le contournement (si elles sont retardées). Le
fichier /etc/sysconfig/udev_retry
configure cela ; tous les mots de ce fichier qui ne sont pas
des commentaires sont considérés comme des noms de sous-systèmes
qu'il faut intercepter au moment du nouvel essai. (Pour trouver
le sous-système d'un périphérique, utilisez udevadm info --attribute-walk.)
Dans les versions récentes, udevd ne crée plus de fichiers
de périphériques dans /dev
. Cela se
gère plutôt dans le noyau, avec le système de fichiers
devtmpfs
. Tout pilote qui
souhaite enregistrer un nœud de périphérique ira sur
devtmpfs
(via le cœur du
pilote) pour le faire. Quand une instance de devtmpfs
est montée sur /dev
, le nœud de périphérique sera créé
au départ avec un nom, des droits et un propriétaire fixes.
Peu de temps après, le noyau enverra un uevent à udevd. À partir des règles
indiquées dans les fichiers contenus dans les répertoires
/etc/udev/rules.d
, /lib/udev/rules.d
et /run/udev/rules.d
, udevd créera les liens
symboliques supplémentaires vers le nœud de périphérique,
ou bien il modifiera ses droits, son propriétaire ou son groupe,
ou l'entrée dans la base de données interne d'udevd concernant cet objet.
Les règles de ces trois répertoires sont numérotées de la même
façon que dans le paquet LFS-Bootscripts et les trois répertoires
sont mis à jour ensemble. Si udevd ne peut pas trouver de
règles pour le périphérique qu'il crée, il en donnera la
propriété et les droits à n'importe quel devtmpfs
utilisé au départ.
Il se peut que les pilotes des périphériques compilés en module
aient aussi des alias compilés. Les alias sont visibles dans la
sortie du programme modinfo et sont souvent liés
aux identifiants spécifiques du bus des périphériques supportés
par un module. Par exemple, le pilote snd-fm801 supporte les périphériques
PCI ayant l'ID fabricant 0x1319 et l'ID de périphérique 0x0801 a
aussi un alias « pci:v00001319d00000801sv*sd*bc04sc01i* ».
Pour la plupart des périphériques, le pilote du bus définit
l'alias du pilote qui gérerait le périphérique via sysfs
. Par exemple, le fichier /sys/bus/pci/devices/0000:00:0d.0/modalias
pourrait contenir la chaîne « pci:v00001319d00000801sv00001319sd00001319bc04sc01i00 ».
Il résultera des règles fournies par défaut qu'udevd fera appel à /sbin/modprobe avec le contenu
de la variable d'environnement de l'uevent MODALIAS
(qui devrait être la même que le contenu
du fichier modalias
dans sysfs),
donc chargera tous les modules dont les alias correspondent à
cette chaîne après les expansions génériques.
Dans cet exemple, cela signifie que, outre snd-fm801, le pilote obsolète (et non désiré) forte sera chargé s'il est disponible. Voir ci-dessous les moyens d'empêcher le chargement des modules indésirables.
Le noyau lui-même est aussi capable de charger des modules de protocole réseau, de support pour des systèmes de fichiers et des NLS sur demande.
Quand vous connectez un périphérique, comme un lecteur MP3 USB, le noyau reconnaît que le périphérique est maintenant connecté et génère un uevent. Cet uevent est alors géré par udevd comme décrit ci-dessus.
Il existe quelques problèmes connus pour la création automatique des nœuds de périphériques :
Udev ne chargera un module que s'il a un alias spécifique au bus
et que le pilote du bus envoie correctement les alias nécessaires
vers sysfs
. Sinon, il faut
organiser le chargement des modules par d'autres moyens. Avec
Linux-3.5.2, Udev est connu pour charger les pilotes correctement
écrits pour les périphériques INPUT, IDE, PCI, USB, SCSI, SERIO
et FireWire.
Pour déterminer si le pilote du périphérique dont vous avez
besoin a le support nécessaire pour Udev, lancez modinfo avec le nom du module
en argument. Puis, essayez de localiser le répertoire du
périphérique sous /sys/bus
et
vérifiez s'il y a un fichier modalias
.
Si le fichier modalias
existe dans
sysfs
, alors le pilote supporte
le périphérique et peut lui parler directement, mais s'il n'a pas
d'alias, c'est un bogue dans le pilote. Chargez le pilote sans
l'aide d'Udev et attendez que le problème soit corrigé plus tard.
S'il n'y a pas de fichier modalias
dans le bon répertoire sous /sys/bus
, cela signifie que les développeurs du
noyau n'ont pas encore ajouté de support modalias à ce type de
bus. Avec Linux-3.5.2, c'est le cas pour les bus ISA. Attendez
que ce problème soit réparé dans les versions ultérieures du
noyau.
Udev n'a pas du tout pour but de charger des pilotes « wrapper » (qui emballent un autre pilote) comme snd-pcm-oss et des pilotes non matériels comme loop.
Si le module « wrapper »
n'améliore que la fonctionnalité fournie par un autre module
(comme snd-pcm-oss
améliore la fonctionnalité de snd-pcm en rendant les cartes son
disponibles pour les applications OSS), configurez modprobe pour charger le
wrapper après qu'Udev ait chargé le module emballé. Pour cela,
ajoutez une ligne « softdep » dans tous les fichiers /etc/modprobe.d/
. Par
exemple :
<filename>
.conf
softdep snd-pcm post: snd-pcm-oss
Remarquez que la commande « softdep » autorise aussi les dépendances
pre:
, ou un mélange de pre:
et de post:
.
Voir la page de manuel de modprobe.d(5)
pour plus d'informations sur la
syntaxe et les possibilités de « softdep ».
Si le module en question n'est pas un emballage et s'avère utile
en tant que tel, configurez le script de démarrage modules pour charger ce module
sur le système de démarrage. Pour cela, ajoutez le nom du module
au fichier /etc/sysconfig/modules
sur une ligne séparée. Ceci fonctionne aussi pour les modules
d'emballage, mais sans être optimal.
Ne compilez pas le module, ou mettez-le en liste noire dans un
fichier /etc/modprobe.d/blacklist.conf
comme nous
l'avons fait avec le module forte dans l'exemple ci-dessous :
blacklist forte
Les modules en liste noire peuvent toujours être chargés manuellement avec la commande explicite modprobe.
Cela se produit habituellement si une règle correspond à un périphérique de façon imprévue. Par exemple, une règle lacunaire peut correspondre à un disque SCSI (comme désiré) et au périphérique SCSI générique du même fabricant (de façon incorrecte). Trouvez la règle défectueuse et affinez-la, à l'aide de la commande udevadm info
Cela peut être une autre manifestation du problème précédent.
Sinon, et si votre règle utilise les attributs de sysfs
, il se peut que ce soit un problème de
timing du noyau, sur le point d'être corrigé dans les noyaux
ultérieurs. Pour le moment, vous pouvez contourner en créant une
règle qui attend l'attribut sysfs
utilisé et en le mettant dans le fichier /etc/udev/rules.d/10-wait_for_sysfs.rules
(créez ce fichier s'il n'existe pas). Merci d'informer la liste
de développement de LFS si vous faites ainsi et que cela vous
aide.
Le texte ci-après suppose que le pilote est compilé de manière statique dans le noyau ou qu'il est déjà chargé comme module, et que vous avez déjà vérifié qu'Udev ne crée pas de périphérique mal nommé.
Udev n'a pas besoin d'information pour créer un nœud de
périphérique si le pilote du noyau n'envoie pas ses données vers
sysfs
. C'est ce qu'il y a de plus
courant avec les pilotes tierce partie à l'extérieur de
l'arborescence du noyau. Créez un nœud de périphérique
statique dans /lib/udev/devices
avec les numéros majeurs/mineurs appropriés (voir le fichier
devices.txt
dans la documentation
du noyau ou la documentation fournie par le fabricant du pilote
tierce partie). Le nœud du périphérique statique sera copié
vers /dev
par le script de
démarrage udev.
Cela est dû au fait qu'Udev, par nature, gère les uevents et charge les modules en parallèle, donc dans un ordre imprévisible. Cela ne sera jamais « corrigé ». Vous ne devriez pas supposer que les noms des périphériques du noyau sont stables. Créez plutôt vos propres règles qui rendent les liens symboliques stables basés sur des attributs stables du périphérique, comme une série de nombre ou la sortie de divers utilitaires *_id installés par Udev. Voir la Section 7.5, « Création de liens symboliques personnalisés vers les périphériques » et la Section 7.2, « Configuration générale du réseau » pour des exemples.
Des documentations supplémentaires sont disponibles sur les sites suivants :
A Userspace Implementation of devfs
http://www.kroah.com/linux/talks/ols_2003_udev_paper/Reprint-Kroah-Hartman-OLS2003.pdf
(NdT : Une implémentation en espace utilisateur de
devfs)
The sysfs
Filesystem
http://www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf
(NdT : Le système de fichiers sysfs
)
Pointers to further reading http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html (NdT : Pointeurs vers de plus amples lectures)