[[udev]]
Piste: » udev
UDEV : Comment ça marche ?
Préambule
Ceci est un tutoriel sur UDEV comme vous l'aurez compris. Il est très complet, mais explique en détail le fonctionnement de la bête.
Je ne vous conseille pas de le lire en diagonale, il contient beaucoup d'informations, toutes nécessaires pour faire fonctionner correctement vos règles.
En général une règle s'écrit en quelques lignes dans un fichiers .rules, mais nécessite beaucoup de rigueur pour qu'elle fonctionne.
Donc prenez votre temps pour tout lire jusqu'au bout et comprendre ce que vous faites !
Les concepts
Terminologie: devfs, sysfs, nodes, etc.
Voici une introduction basique.
Sur les systèmes à base de Linux, le répertoire /dev sert à contenir les périphériques sous forme de fichier, les nodes, qui se rapportent aux périphériques système. Chaque "node" se réfère à un périphérique, qui peut -ou pas- exister. les applications utilisateur peuvent utiliser ces périphériques "nodes" pour interagir avec le serveur graphique. Par exemple, le serveur X va "écouter" /dev/input/mice qui peut se référer à la souris et faire bouger le pointeur à l'écran.
Le répertoire original /dev contient tous les périphériques du système. C'est pourquoi le répertoire /dev est si volumineux. Devfs a été créé pour une utilisation plus simple, mais ce système a démontré qu'il y a parfois des problèmes compliqués à résoudre.
Udev est le nouveau système pour gérer le répertoire /dev, désigné pour éclaircir les questions sur les précédentes versions /dev, et fournir une connexion robuste. Dans le but de créer et nommer les périphériques /dev, "nodes" qui correspond donc aux périphériques système, udev relie les informations données par sysfs avec les règles, données par l'utilisateur. Ce wiki a pour but d'expliquer comment écrire les règles udev.
Sysfs est le nouveau système de fichiers des kernels 2.6. Il est géré par le kernel, et exporte les informations basiques sur les périphériques actuellement connectés au système. Udev peut utiliser ces informations pour créer les périphériques "nodes" correspondants à votre ordinateur. Sysfs est monté sur /sys et vous pouvez le parcourir. Vous pouvez regarder ces fichiers avant de regarder udev. Dans ce wiki, j'utiliserai /sys et sysfs, qui signifient la même chose.
Pourquoi ?
Les règles udev sont flexibles et très puissantes. Voici quelques exemples de ce que vous pouvez faire :
- Renommer le nom donné par défaut à périphérique "node"
- Donner un nom alternatif/persistant à un périphérique "node" en créant un lien symbolique pour ce périphérique "node"
- Nommer un périphérique "node" basé sur la sortie d'un programme
- Changer les permissions et les propriétés d'un périphérique "node"
- Lancer un script quand un périphérique "node" est créé ou supprimé (en général pour un périphérique externe ou qui se branche à chaud comme l'USB)
- Renommer les interfaces réseaux
L'écriture de règles n'est pas une solution s'il n'existe pas de périphérique "node" pour votre périphérique particulier. S'il n'y a pas de règle, udev va créer le périphérique "node" avec le nom donné par défaut par le kernel.
Il y a plusieurs avantages à avoir un nom de périphérique constant. Supposons que vous ayez deux périphériques USB : une webcam et un disque flash USB. Ces périphériques sont normalement assignés aux périphériques "nodes" /dev/sda et /dev/sdb, mais cet ordre exact dépend de l'ordre dans lequel ils ont été connectés. Donc il est plus pratique de nommer chaque périphérique à chaque fois de la même manière, par exemple /dev/camera et /dev/flashdisk.
Donner un nom persistant à un périphérique
Udev fournit un nom persistant pour certains types de périphériques non connectés. C'est un dispositif très pratique, et donc, cela signifie que vous n'avez rien à faire : vous n'avez pas besoins d'écrire de règle.
Udev fournit des noms persistants pour les périphériques de stockage dans le répertoire /dev/disk. Pour les voir, vous pouvez utilisez la commande suivante :
ls -lR /dev/disk
Cela fonctionne pour tous les types de périphériques de stockage. Par exemple, udev a créé /dev/disk/by-id/scsi-SATA_ST3120827AS_4MS1NDXZ-part3 qui est un lien symbolique vers le nom persistant de ma partition root. Udev crée /dev/disk/by-id/usb-Prolific_Technology_Inc._USB_Mass_Storage_Device-part1 quand je branche mon disque flash USB , qui est aussi un nom persistant.
Rédigez vos régles
Fichiers de règles et syntaxes
Pour décider comment nommer un périphérique et quelles actions faire, udev utilise une série de fichiers de règles. Ces fichiers se trouvent dans le répertoire /etc/udev/rules.d, et doivent tous avoir l'extension .rules . Les règles udev créées par défaut sont dans le fichier /etc/udev/rules.d/50-udev.rules1). Il pourrait être intéressant d'y jeter un oeil – il contient quelques exemples-, et certaines règles contiennent un exemple de sortie de devfs que vous trouverez dans /dev par défaut. Cependant, il n'est pas conseillé d'écrire de règle directement dedans.
Les fichiers de /etc/udev/rules.d/ sont triés par ordre alphabétique, et dans certaines circonstances, l'ordre dans lequel ils sont analysés est important. En général, vous voulez que vos propres règles soient prises en compte avant les règles créées par défaut, donc je vous suggère de créer votre fichier comme ceci /etc/udev/rules.d/10-local.rules et écrire vos propres règles dans ce fichier.
Dans un fichier de règles, les lignes commençant par "#" sont traitées comme des commentaires. Toutes les autres lignes sont donc considérées comme des règles. Les règles s'écrivent sur une seule ligne (on ne les coupe pas par un passage à la ligne avec ENTRER par exemple).
Un périphérique peut être contrôlé par plusieurs règles. Ceci peut être avantageux, par exemple, nous pouvons écrire deux règles pour un périphérique, qui peuvent donner un nom différents pour le même périphérique. Les deux règles seront créées même si ces règles sont dans des fichiers séparés. Il est important de comprendre que udev ne s'interrompt pas quand il trouve une règle, il continue sa recherche et tente d'appliquer chaque règle trouvée.
Syntaxe d'une règle
Chaque règle est construite à partir d'une série de valeurs, séparées par des virgules. Les valeurs trouvées sont les conditions utilisées pour identifier le périphérique sur lequel la règle agit. Quand toute la série de valeurs de la règle correspondent bien au périphérique, alors seulement la règle est appliquée. Chaque règle doit se composer d'au moins une clé et d'un assignement de clé.
Par exemple :
- KERNEL=="hdb", NAME="my_spare_disk"
Cette règle inclut une clé (KERNEL) et un assignement de clé (NAME). La sémantique de ces clés et leurs propriétés seront détaillées par la suite. Il est important de noter que la clé est liée à sa valeur par un double égal ( == ), alors que la clé d'assignement est liée à sa valeur par un simple égal ( = ).
Règles basiques
Udev peut utiliser plusieurs clés pour écrire des règles et donc pour paramétrer un périphérique de manière très précise. Les clés les plus communes sont introduites comme ci dessous, les autres cas seront traités plus loin. Pour la liste complète, regardez en console l'aide de udev avec la commande man udev.
- KERNEL – pour le nom du périphérique donné par le kernel
- SUBSYSTEM - pour le nom du sous système du périphérique
- DRIVER - pour le pilote du périphérique
Après avoir utilisé une série de clés pour définir précisément le périphérique, udev vous donne le contrôle par la suite, grâce aux clés d'assignement. Pour la liste complète des clés d'assignement, regardez en console l'aide de udev avec la commande man udev . Les clés d'assignement les plus basiques se trouvent ci-dessous. Les autres cas seront traités plus loin.
- NAME – nom du périphérique "node"
- SYMLINK - Liste des liens symboliques étant les noms alternatifs du périphérique node
Comme il l'a été dit ci-dessus, udev crée seulement un seul vrai périphérique "node" pour un périphérique. Si vous souhaitez fournir des noms alternatifs pour ce périphérique "node", utilisez le lien symbolique fonctionnel. Avec l'assignement SYMLINK, vous créez une liste de liens symboliques, qui pointent vers le périphérique node. Pour utiliser ces liens, nous introduisons un nouvel opérateur : +=. Vous pouvez utiliser plusieurs symlinks sur la liste quelque soit la règle en les séparant par un espace.
- KERNEL=="hdb", NAME="my_spare_disk"
Soit la règle : «Nommer un périphérique nommé par le kernel hdb en my_spare_disk». Le périphérique "node" apparaîtra sous /dev/my_spare_disk.
- KERNEL=="hdb", DRIVER=="ide-disk", SYMLINK+="sparedisk"
Soit la règle : «Nommer un périphérique nommé par le kernel hdb» ET «quand le pilote est ide-disk. Nommer le périphérique "node" avec le nom par défaut et créer un lien symbolique nommé sparedisk». Notez que nous n'avons pas spécifié de nom au périphérique "node", donc udev utilisera celui par défaut. Pour préserver la disposition standard du /dev, vos propres règles seront écrites sans NAME mais créez des SYMLINKs et/ou donner d'autres assignements.
- KERNEL=="hdc", SYMLINK+="cdrom cdrom0"
La règle précédente est probablement la plus commune que vous écrirez. Cela crée deux liens symboliques /dev/cdrom et /dev/cdrom0, qui pointeront tous deux sur /dev/hdc. Une fois de plus, pas d'assignement NAME spécifié, donc le nom par défaut donné par le kernel (hdc) sera utilisé.
Attributs sysfs
Les clés introduites précédemment ont des possibilités limitées. Donc nous avons besoin d'un contrôle plus précis : nous voulons identifier les périphériques avec des options avancées comme le numéro du vendor, le nom exact du produit, le numéro de série, la capacité de stockage, le nombre de partitions, etc. Certains pilotes exportent ces informations dans le sysfs, et udev vous autorise à utiliser les informations de sysfs pour vos propres règles, à l'aide de la clé SYSFS ainsi que différentes syntaxes.
Voici plusieurs exemples utilisant sysfs. Plus de détails par la suite.
- KERNEL=="sda", SYSFS{model}=="ST3120827AS", SYMLINK+="my_hard_disk"
- SUBSYSTEM=="block", SYSFS{size}=="234441648", SYMLINK+="my_disk"
- BUS=="usb", SYSFS{manufacturer}=="OLYMPUS", SYSFS{product}=="X250,D560Z,C350Z", SYMLINK+="camera"
Substitution simple de caractères
Pour écrire des règles agissant sur plusieurs périphériques similaires, les opérateurs udev comme printf sont très utiles. Vous pouvez inclure simplement ces opérateurs dans n'importe quel assignement dans vos règles, et udev les évaluera quand ils seront éxecutés.
Les opérateurs les plus communs sont %k et %n. %k évalue le nom assigné par le kernel pour le périphérique donné, e.g. sda3 pour le périphérique qui apparaîtra par défaut sur /dev/sda3. %n évalue le numéro donné par le kernel pour le périphérique donné (le numéro de partition pour le périphérique de stockage), e.g. 3 pour /dev/sda3.
Udev fournit d'autres opérateurs de substitution pour créer des fonctions plus avancées. Consultez l'aide de udev (en console, tapez man udev) après avoir fini de lire ce document. Il y a une syntaxe alternative pour ces opérateurs - $kernel et $number pour les exemples précédents. Dans ce cas, si vous voulez utiliser un % littéral dans une règle vous devrez taper %%, et si vous voulez utiliser un $ littéral dans une règle vous devrez taper $$.
Par exemple :
- KERNEL=="mice", NAME="input/%k"
- KERNEL=="loop0", NAME="loop/%n", SYMLINK+="%k"
La première règle assure que le périphérique "node" apelé souris apparaîtra exclusivement dans le répertoire /dev/input (par défaut il aurait dû être dans /dev/mice). La deuxième règle assure que le périphérique "node" nommé loop0 est créé dans /dev/loop/0 mais crée aussi un lien symbolique /dev/loop0 comme à l'habitude.
Mais on peut se demander quel est le véritable intérêt de ces deux règles, car elles peuvent être utilisées sans aucun opérateur de substitution. Le véritable intérêt de ses substitutions va vous être expliqué dans la section suivante.
Subsitution évoluée de caractères
Comme pour le cas utiliser exactement les chaînes de caractères, udev vous permet d'utiliser le modèle shell . Il y a trois modèles supportés :
- * - remplace n'importe quel caractère, sans limite de caractères
- ? - remplace exactement un seul caractère
- [] - force le caractère (un seul) entre crochets, les extensions sont permises
Quelques exemples. Notez l'utilisation des opérateurs de substitution.
- KERNEL=="fd[0-9]*", NAME="floppy/%n", SYMLINK+="%k"
- KERNEL=="hiddev*", NAME="usb/%k"
La première règle est pour un lecteur de disquette, et assure que les périphériques "nodes" sont placés dans le répertoire /dev/floppy, ce qui est fait par défautpar udev. La seconde règle assure que le périphérique hiddev se trouve uniquement dans le répertoire /dev/usb.
Utilisation de sysfs
Organisation de sysfs
L'utilisation de sysfs a été brièvement évoqué ci-dessus. Dans le but d'écrire des règles basées sur ces informations, vous devez d'abord connaître le nom des attributs et leurs valeurs. Sysfs a une structure très simple. Il est logiquement divisé en répertoires. Chaque répertoire contient un certain nombre de fichiers (attributs) qui en général contiennent une seule valeur. Certains liens symboliques sont présents, parcourant plusieurs branches de "l'arbre" sysfs.
Certains répertoires sont situés sur les niveaux supérieurs du dispositif. Le niveau supérieur lie d'autres parties de sysfs vers le périphérique en question. Les chemins des périphériques du niveau supérieur sont classifiés dans le répertoire sysfs, contenant un fichier dev, la commande suivante va vous les lister :
find /sys -name dev
Par exemple, sur mon système, le répertoire /sys/block/sda est le chemin du périphérique de mon disque dur. Il est lié au contrôleur avec le lien symbolique /sys/block/sda/device/, qui en même temps est lié au pilote du périphérique avec le lien symbolique /sys/block/sda/device/driver/.
Quand vous écrivez des règles basées sur les informations sysfs, vous devez simplement remplacer les attributs par ceux trouvés dans ces fichiers. Par exemple, je peux lire la taille de mon disque dur avec :
cat /sys/block/sda/size 234441648
Dans une règle udev, je peux utiliser SYSFS{size}=="234441648" pour identifier ce disque. Comme udev fait une recherche dans toute la branche du périphérique, je peux aussi choisir d'afficher une autre partie de cette branche.(e.g. attributes dans /sys/class/block/sda/device/). Cependant il y a d'autres choses à prendre en considération quand on utilise d'autres parties de la branche, comme il l'est décrit plus loin.
Bien que cela serve d'introduction utile pour la structure du sysfs et voir précisément le fonctionnement de udev, le changement avec sysfs est souvent une perte de temps et qui n'est donc pas nécessaire.
udevinfo
Udevinfo est probablement l'outil le plus puissant pour construire des règles. Tout ce que vous devez connaître est le périphérique sysfs du périphérique en question. Par exemple :
udevinfo -a -p /sys/block/sda
------------------**INFORMATIONS DE TYPE 1**------------------
looking at device '/block/sda':
KERNEL=="sda"
SUBSYSTEM=="block"
SYSFS{stat}==" 128535 2246 2788977 766188 73998 317300 3132216 5735004 0 516516 6503316"
SYSFS{size}=="234441648"
SYSFS{removable}=="0"
SYSFS{range}=="16"
SYSFS{dev}=="8:0"
------------------**INFORMATIONS DE TYPE 2**------------------
looking at device '/devices/pci0000:00/0000:00:07.0/host0/target0:0:0/0:0:0:0':
ID=="0:0:0:0"
BUS=="scsi"
DRIVER=="sd"
SYSFS{ioerr_cnt}=="0x0"
SYSFS{iodone_cnt}=="0x31737"
SYSFS{iorequest_cnt}=="0x31737"
SYSFS{iocounterbits}=="32"
SYSFS{timeout}=="30"
SYSFS{state}=="running"
SYSFS{rev}=="3.42"
SYSFS{model}=="ST3120827AS "
SYSFS{vendor}=="ATA "
SYSFS{scsi_level}=="6"
SYSFS{type}=="0"
SYSFS{queue_type}=="none"
SYSFS{queue_depth}=="1"
SYSFS{device_blocked}=="0"
Comme vous pouvez le voir, udevinfo renvoie une liste d'informations que vous pouvez utiliser dans vos règles udev. Avec l'exemple précédant je peux créer une règle pour ce périphérique :
SUBSYSTEM=="block", SYSFS{size}=="234441648", NAME="my_hard_disk"
BUS=="scsi", SYSFS{model}=="ST3120827AS", NAME="my_hard_disk"
Vous avez pu voir la séparation des informations (type 1 et type 2) dans ces exemples, cela montre que vous ne pouvez pas combiner ces informations dans une règle, sinon elle ne fonctionnera pas.En effets ils sont considérés comme des périphériques différents (looking at device '/block/sda' et looking at device '/devices/pci0000:00/0000:00:07.0/host0/target0:0:0/0:0:0:0' sont deux périphériques distincts).
Par exemple, cette règle est invalide :
#**règle fausse**
SUBSYSTEM=="block", SYSFS{size}=="234441648", SYSFS{model}=="ST3120827AS", NAME="my_hard_disk"
Normalement vous aurez beaucoup d'attributs, et vous devez en choisir quelques uns (de la même section) pour construire votre règle. En général, vous voudrez choisir les attributs qui identifient votre périphérique de façon persistante. Dans ces exemples j'ai choisi la taille et le numéro de série de mon disque. Je n'ai pas utilisé les nombres sans signification comme SYSFS{iodone_cnt}=="0x31737".
Notez aussi que les attributs donnés par udevinfo sont séparés par des espaces. (e.g. voyez ST3120827AS dans l'exemple précédent). Dans vos règles, vous pouvez spécifier facilement les espaces supplémentaires, ou vous pouvez les couper comme je l'ai fait.
La où udevinfo se complique, c'est que vous devez connaître les branches supérieures (/sys/block/sda dans l'exemple précédant). Ce n'est pas toujours évident. Cependant, comme en général vous écrivez des règles pour les périphériques "nodes" existants, vous pouvez utiliser udev pour trouver la branche supérieure :
udevinfo -a -p $(udevinfo -q path -n /dev/sda)
Méthodes Alternatives
Bien que udevinfo soit la méthode la plus sûre pour lister les attributs exacts pour construire vos règles, certains utilisateurs préféreront utiliser d'autres outils. Les outils comme usbview montrent des informations similaires, pouvant être utilisées pour créer des règles.
Le coin du geek
Créer des permissions et des propriétés
Udev vous permet de gérer dans vos règles les propriétés et les permissions de chaque périphérique.
L'assignement GROUP vous permet de définir à quel groupe appartient un périphérique "node". Dans cet exemple le périphérique framebuffer appartient au groupe Vidéo :
- KERNEL=="fb[0-9]*", NAME="fb/%n", SYMLINK+="%k", GROUP="video"
La clé OWNER, peut-être moins intéressante, vous permet de définir les permissions d'un utilisateur pour le périphérique "node". Dans cet exemple, l'utilisateur John sera le seul utilisateur à avoir accès au lecteur de disquettes :
- KERNEL=="fd[0-9]*", OWNER="john"
Par défaut, udev crée les permissions pour "node" avec les permissions 0660 (lire/écrire pour tous les utilisateurs/groupes). Si c'est nécessaire, vous pouvez les modifier pour certains périphériques en utilisant les règles avec l'assignement MODE. Cet exemple définit quel périphérique peut être utilisé par tout le monde :
- KERNEL=="inotify", NAME="misc/%k", SYMLINK+="%k", MODE="0666"
Utiliser des programmes externes comme noms de périphériques
Dans certaines circonstances, vous pouvez avoir besoins de plus de flexibilité que les règles udev en donnent. Dans ce cas vous pouvez demander à udev de lancer un programme et utiliser ce qui est en sortie de ce programme pour créer le nom de périphérique.
Pour utiliser cette fonction, vous devez simplement spécifier la ligne de commande entière du programme à utiliser (ainsi que ses paramètres) dans l'assignement PROGRAM, vous pouvez trouver des variantes d'utilisation du %c dans les sections NAME/SYMLINK.
Les exemples suivants se référent a un programme fictif situé dans /bin/device_namer. Device_namer prend un argument en ligne de commande qui est le nom du kernel du périphérique. Basé sur ce nom de kernel, device_namer donne les informations de sortie stdout, séparées en plusieurs parties. Chaque partie est un seul mot, et les parties sont séparées par un seul espace.
Dans ce premier exemple, nous considérons que les informations en sortie de device_namer sont un nombre de parties, chacune forme un lien symbolique pour le périphérique en question.
- KERNEL=="hda", PROGRAM="/bin/device_namer %k", SYMLINK+="%c"
L'exemple suivant considère que les informations en sortie de device_namer contiennent deux parties, la première est le nom du périphérique, et la seconde est le nom pour un lien symbolique additionnel. Nous introduisons maintenant la substitution %c{N}, en référence au nombre de parties des informations en sortie :
- KERNEL=="hda", PROGRAM="/bin/device_namer %k", NAME="%c{1}", SYMLINK+="%c{2}"
Le prochain exemple considère que les informations en sortie de device_namer contiennent le nom du périphérique, suivit par un nombre de parties qui pointent vers un lien symbolique. Nous introduisons maintenant la substitution %c{N+}, qui évalue les parties N, N+1, N+2, ... jusqu'à la dernière information de sortie.
- KERNEL=="hda", PROGRAM="/bin/device_namer %k", NAME="%c{1}", SYMLINK+="%c{2+}"
Les parties créées à partir des informations de sorties peuvent être utilisées dans n'importe quelle clé d'assignement, et pas seulement avec NAME et SYMLINK. L'exemple suivant utilise un programme fictif qui détermine le groupe qui doit avoir les droits de ce périphérique :
- KERNEL=="hda", PROGRAM="/bin/who_owns_device %k", GROUP="%c"
Exécuter certains programmes selon certains événements
Une autre raison d'écrire des règles udev est de lire un programme quand un périphérique est connecté ou déconnecté. Par exemple, vous voulez lancer un script qui télécharge automatiquement les photos de votre appareil photo quand il est connecté.
Ne confondez pas ceci avec la fonction PROGRAM décrite avant. PROGRAM sert à lancer des programmes qui produisent des noms de périphériques (et qui ne font rien d'autre). Quand ces programmes sont éxecutés, le périphérique "node" n'a pas encore été créé, donc faire une action juste après sur ce périphérique n'est pas possible.
La fonction introduite ici vous permet de lire un programme après que le périphérique soit mis en place. Ce programme peut interagir avec le périphérique, cependant il ne doit pas être éxecuté plus d'un certain temps, car udev est mis en pause quand ces programmes sont lancés. Ce qu'il ne faut pas négliger est de s'assurer que le programme s'arrête immédiatement de lui même.
Voici un exemple de règle qui utilise l'assignement RUN :
- KERNEL=="sdb", RUN+="/usr/bin/my_program"
Quand /usr/bin/my_program est éxecuté, plusieurs parties de l'environnement udev sont accessibles en tant que variables d'environnement, ceci inclue les clés comme SUBSYSTEM. Vous pouvez aussi utiliser la variable d'environnement ACTION pour détecter si le périphérique est connecté ou pas - ACTION peut respectivement "ajouter" ou "supprimer".
Interactions avec l'environment
Udev fournit une clé ENV pour les variables d'environnement qui peuvent être utilisées à la fois pour trouver et assigner.
Pour le cas de l'assignement, vous pouvez placer des variables d'environnement que vous pourrez retrouver par la suite. Vous pouvez aussi placer des variables d'environnement que vous pouvez utiliser avec n'importe quel programme externe à l'aide des techniques décrites plus haut. Un exemple fictif de règle qui crée une variable d'environnement :
- KERNEL=="fd0", SYMLINK+="floppy", ENV{some_var}="value"
Dans le cas de la recherche, vous pouvez vous assurer que les règles se lancent seulement selon une variable d'environnement. Notez que l'environnement que udev voit ne sera pas le même que celui que l'utilisateur voit en console. Cette règle fictive montre ceci :
- KERNEL=="fd0", ENV{an_env_var}=="yes", SYMLINK+="floppy"
Cette règle crée le lien /dev/floppy link seulement si $an_env_var est égal à "yes" dans l'environnement udev.
Options additionnelles
Un autre assignement qui montre l'utilité de la liste OPTIONS. Plusieurs options sont possibles :
- all_partitions – crée autant de partitions que possible pour un périphérique bloc, plutôt que seulement celles créés au démarrage.
- ignore_device - ignore complétement l'événement
- last_rule – s'assure qu'aucune règle qui suit ne fonctionnera
Par exemple, cette la règle place le groupe ownership pour mon disque dur, et s'assure qu'aucune règle qui suit n'aura d'effet dessus :
- KERNEL=="sda", GROUP="disk", OPTIONS+="last_rule"
Exemples
Imprimante USB
J'allume mon imprimante, elle est assignée au périphérique /dev/lp0. Non satisfait de ce nom, je décide de créer une règle udev pour le changer :
udevinfo -a -p $(udevinfo -q path -n /dev/lp0)
looking at the device chain at '/sys/devices/pci0000:00/0000:00:02.1/usb3/3-3':
BUS=="usb"
SYSFS{manufacturer}=="EPSON"
SYSFS{product}=="USB Printer"
SYSFS{serial}=="L72010011070626380"
Ma règle devient :
BUS=="usb", SYSFS{serial}=="L72010011070626380", SYMLINK+="epson_680"
Appareil photo USB
Comme la plupart des appareils photo, mon appareil photo est identifié comme un disque dur externe branché en USB, utilisant le transport SCSI. Pour accéder à mes photos, je monte le périphérique et je copie les images sur mon disque dur.
Tous les appareils photo ne fonctionnent pas forcément avec cette méthode : certains utilisent un protocole non-storage comme les appareils photo supportés par gphoto2. Dans le cas de gphoto, vous ne devez pas faire de règle d'écriture pour votre dispositif, car le contrôle est simplement fait par l'espace utilisateur (à l'opposé d'un driver spécifique du kernel).
Un problème commun avec les appareils photo USB est qu'ils sont identifiés comme des disques contenant une seule partition, dans ce cas /dev/sdb avec /dev/sdb1. Le périphérique sdb est inutile pour moi, mais sdb1 est intéressant – c'est celui que je veux monter. Il y a un problème car sysfs est attaché, les attributs utiles produits par udevinfo pour /dev/sdb1 sont identiques que ceux de /dev/sdb. Ce résultat montre à la fois le disque raw et la partition, comme ce n'est pas ce que nous voulons, notre règle doit être spécifique.
Pour résoudre ceci, vous devez simplement penser à ce qui diffère entre sdb et sdb1. C'est étonnement simple : seul le nom diffère, donc nous pouvons juste utiliser le modèle très simple donné dans le champ NAME.
udevinfo -a -p $(udevinfo -q path -n /dev/sdb1)
looking at device '/devices/pci0000:00/0000:00:02.0/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0':
ID=="6:0:0:0"
BUS=="scsi"
DRIVER=="sd"
SYSFS{rev}=="1.00"
SYSFS{model}=="X250,D560Z,C350Z"
SYSFS{vendor}=="OLYMPUS "
SYSFS{scsi_level}=="3"
SYSFS{type}=="0"
Ma règle :
KERNEL=="sd?1", BUS=="scsi", SYSFS{model}=="X250,D560Z,C350Z", SYMLINK+="camera"
Disque Dur USB
Pour un Disque Dur USB, c'est comparable à l'exemple de l'appareil photo USB que je viens de décrire, cependant le modèle à utiliser est différent. Pour l'exemple de l'appareil photo, j'ai expliqué que le périphérique sdb ne m'intéressais pas – ceci ne sert que pour le partitionnement (e.g. avec fdisk), et pourquoi voudrai-je partitionner mon appareil photo !?
Bien sûr, si vous avez un disque dur USB de 100GB, c'est très compréhensible de vouloir le partitionner, dans ce cas nous pouvons tirer avantage de la SUBSTITUTION de udev :
- BUS=="usb", KERNEL=="sd*", SYSFS{product}=="USB 2.0 Storage Device", NAME="%k", SYMLINK+="usbhd%n"
Cette règle crée des liens symlik comme ceci :
- /dev/usbhd – Le périphérique 'fdiskable'
- /dev/usbhd1 – La première partition (montable)
- /dev/usbhd2 – La seconde partition (montable)
Lecteurs de carte USB
Les Lecteurs de carte USB (CompactFlash, SmartMedia, etc) sont encore un autre type de périphériques de stockage USB avec un usage différent.
Ces périphériques n'informent pas l'ordinateur hôte sur le changement de média. Donc, si vous connectez le périphérique sans carte, et que ensuite vous y insérez une carte, l'ordinateur ne va pas le détecter, et vous n'aurez pas accès à la partition de votre carte.
La seule solution est de tirer avantage de l'option all_partitions, qui va créer 16 partitions pour chaque périphérique, illustré dans cet exemple :
- BUS=="usb", SYSFS{product}=="USB 2.0 CompactFlash Reader", SYMLINK+="cfrdr%n", OPTIONS+="all_partitions"
Vous aurez donc les périphériques : cfrdr, cfrdr1, cfrdr2, cfrdr3, ..., cfrdr15.
Palm USB
Ces périphériques fonctionnent comme des périphériques USB-serial, donc par défaut, vous n'aurez que le périphérique ttyUSB1. Les utilitaires palm sont reliés à /dev/pilot, certains utilisateurs voudront une règle qui gère cela. Le post du blog de Carsten Clasohm semblent donner la solution. Voici La règle de Carsten :
- BUS=="usb", SYSFS{product}=="Palm Handheld", KERNEL=="ttyUSB*", SYMLINK+="pilot"
Notez que SYSFS{product} est différent selon le matériel, donc pensez à le vérifier avec udevinfo.
Lecteurs CD/DVD
J'ai deux lecteurs optiques : un lecteur DVD (hdc), et un graveur DVD (hdd). Je ne pense pas les modifier, à moins de les bouger physiquement. Cependant certains utilisateur souhaiteront qu'ils soient détectés en tant que /dev/dvd pour plus de facilités.
Comme nous le savons pour les noms donnés par le Kernel pour ces périphériques, l'écriture de règles est simple.
Par exemple :
- BUS=="ide", KERNEL=="hdc", SYMLINK+="dvd", GROUP="cdrom"
- BUS=="ide", KERNEL=="hdd", SYMLINK+="dvdrw", GROUP="cdrom"
Interfaces Réseau
Etant référencés par noms, les interfaces réseau n'ont pas par défaut de nom de périphérique attribué. En dépit de cela, l'écriture de règle est presque la même.
Il est donc logique de simplement utiliser l'adresse MAC de votre interface dans la règle, comme elle est unique. Cependant, soyez certain d'utiliser l'adresse MAC exacte, comme elle l'est montrée dans udevinfo, sinon votre règle ne fonctionnera pas.
udevinfo -a -p /sys/class/net/eth0
looking at class device '/sys/class/net/eth0':
SYSFS{address}=="00:52:8b:d5:04:48"
Voilà la règle :
- KERNEL=="eth*", SYSFS{address}=="00:52:8b:d5:04:48", NAME="lan"
Vous devrez recharger le pilote pour appliquer cette règle. Vous pouvez décharger et recharger le module, ou simplement redémarrer votre ordinateur. Vous devrez aussi reconfigurer votre système pour utiliser «lan» à la place de «eth0». J'ai eu quelques problèmes pour le faire fonctionner (l'interface n'a pas été renommée) tant que je n'avais pas complétement retiré toutes les références à «eth0». Après ça, vous pourrez utiliser «lan» à la place de «eth0» dans n'importe quel utilitaire comme ifconfig.
Joystick
Les joysticks apparaissent comme /dev/input/jsX et certains /dev/input/eventX. Certaines applications (Wine par exemple) veulent accéder aux joysticks comme /dev/input/eventX mais cela n'est pas forcément possible du fait des droits de ces fichiers :
On peut ajouter la règle :
* KERNEL=="event[0-9]*", ENV{ID_CLASS}=="joystick", MODE="0666"
ou
* KERNEL=="event[0-9]*", ENV{ID_CLASS}=="joystick", GROUP="SOMEGROUP", MODE="0660"
qui donne les droits de lecture/écriture à tout le monde (on peut modifier cet exemple pour donner les droits à un groupe).
Tests et debugging
Activez vos règles
En vous assurant d'être sur un kernel avec le support inotify, udev va automatiquement monitorer votre répertoire de règles et prendre en compte automatiquement les modifications faites dans vos règles.
A l'encontre de ceci, udev ne remontera pas automatiquement les périphériques mais tentera d'appliquer les règles. Par exemple, si vous écrivez une règle pour ajouter un lien symbolique pour votre appareil photo quand votre appareil photo est branché au pc, ne vous attendez pas à ce que le lien symbolique soit créé. Pour créer le lien symbolique, vous pouvez simplement débrancher et rebrancher votre appareil photo au pc, et dans le cas où le périphérique ne peut pas être débranché, vous pouvez lancer en console udevtrigger.
Si votre kernel n'a pas le support, les nouvelles règles ne seront pas détectées automatiquement. Dans ce cas, vous devez lancer en console udevcontrol reload_rules après avoir créé une règle ou modifié un fichier de règles pour que cela prenne effet.
udevtest
Si vous connaissez la branche qui gère votre périphérique dans sysfs, vous pouvez utiliser udevtest pour voir les actions que udev va faire. Cela pourra vous aider pour corriger vos règles. Par exemple, vous voulez vérifier une règle qui agit sur /sys/class/sound/dsp :
udevtest /class/sound/dsp main: looking at device '/class/sound/dsp' from subsystem 'sound' udev_rules_get_name: add symlink 'dsp' udev_rules_get_name: rule applied, 'dsp' becomes 'sound/dsp' udev_device_event: device '/class/sound/dsp' already known, remove possible symlinks udev_node_add: creating device node '/dev/sound/dsp', major = '14', minor = '3', mode = '0660', uid = '0', gid = '18' udev_node_add: creating symlink '/dev/dsp' to 'sound/dsp'
Notez que le préfixe /sys a été supprimé des arguments de la ligne de commande de udevtest, la raison est que udev opère sur le chemin du périphérique. Notez aussi que udevtest est juste un outil de test/debug, cela ne créera pas de périphérique, malgré ce que udevtest vous dit (c'est une simulation) !
Auteur et contact
Ce document a été rédigé originalement en anglais par Daniel Drake dan@reactivated.net et traduit par Acp. Les retours sont appréciés par Denis Drake :) (en anglais).
Pour le support, envoyez un mail à la mailing liste de linux hotplug : linux-hotplug-devel@lists.sourceforge.net.
Copyright (C) 2003-2006 Daniel Drake. Ce document est licencié par GNU General Public License, Version 2
Contributeurs : Acp