7.4. Gestione dei dispositivi e dei moduli in un sistema LFS

Nel Capitolo 6, è stato installato il pacchetto Udev. Prima di scendere nel dettaglio di come funziona, facciamo un breve accenno al precedente metodo per la gestione delle periferiche/dispositivi.

I sistemi Linux usano tradizionalmente un metodo statico di creazione dei dispositivi, in questo modo si creano molti device node nella directory /dev (qualche volta letteralmente migliaia di nodi), anche se non esiste in quel momento l'hardware corrispondente. Questo avviene tramite lo script MAKEDEV, che contiene un numero di chiamate al programma mknod, con i relativi numeri major e minor della periferica, pari ad ogni possibile periferica che possa esistere al mondo.

Usando il metodo udev, vengono creati i device node solo per quelle periferiche che vengono trovate dal kernel. Dato che questi device node vengono creati ad ogni avvio del sistema, vengono memorizzati in un file system tmpfs (un file system virtuale che risiede interamente in memoria). Dato che i device node non richiedono molto spazio disco, la memoria usata è irrisoria.

7.4.1. Cronistoria

Nel febbraio 2000, un nuovo filesystem chiamato devfs venne intergrato nel kernel 2.3.46 e divenne disponibile con la serie 2.4 dei kernel stabili. Sebbene fosse presente nei sorgenti del kernel, questo metodo di creazione dinamica dei dispositivi non ha mai ricevuto un consenso ed un supporto unanime da parte degli sviluppatori del kernel.

Il problema principale dell'approccio adottato da devfs è stato la gestione dell'identificazione delle periferiche, della loro creazione e nomenclatura. D'altra parte, il problema della nomenclatura dei device node era forse il più critico. È generalmente accettato che se i nomi dei dispositivi sono configurabili la politica di come chiamare le periferiche deve essere lasciata all'amministratore di sistema e non essere imposta da un particolare sviluppatore. Il file system devfs soffre anche di condizioni che sono inerenti alla propria progettazione e non possono essere corrette senza una sostanziale revisione del kernel. È stato anche contrassegnato come deprecato a causa della mancanza di manutenzione.

Con lo sviluppo dell'albero instabile del kernel della serie 2.5, che ha poi portato alla serie 2.6 dei kernel stabili, è stato introdotto un nuovo filesystem virtuale chiamato sysfs. Quello che fa sysfs è esportare una vista della configurazione del sistema hardware nello userspace. Con questa rappresentazione visibile dallo userspace, la possibilità di vedere un sostituto di devfs è diventata molto più realistica.

7.4.2. Implementazione di Udev

7.4.2.1. Sysfs

Il filesystem sysfs è stato menzionato brevemente sopra. Ci si può meravigliare di come sysfs conosca le periferiche presenti sul sistema e quale numero di dispositivo usare per loro. I driver che sono stati compilati direttamente nel kernel registrano i propri oggetti nel sysfs non appena sono riconosciuti dal kernel. Per i driver compilati come moduli, questo succede non appena il modulo viene caricato. Una volta che il filesystem sysfs viene montato (in /sys), i dati che i driver compilati nel kernel registrano attraverso sysfs divengono disponibili allo userspace dei processi e a udevd per la creazione dei device node.

7.4.2.2. Il bootscript Udev

Lo script di avvio S10udev si occupa della creazione di questi device node quando Linux viene avviato. Questo script disattiva il gestore di uevent dalla /sbin/hotplug predefinita. Questo viene fatto perché il kernel non ha più bisogno di richiamare un binario esterno. Invece udevd ascolterà su un socket netlink per gli uevent che il kernel raccoglie. Dopo, il bootscript copia ogni device node statico che esiste in /lib/udev/devices in /dev. Questo è necessario perché alcuni dispositivi, directory, e symlink sono necessari prima che i processi di gestione dinamica dei dispositivi siano disponibili durante i primi passi dell'avvio di un sistema. La creazione di device node statici in /lib/udev/devices è una soluzione semplice anche per i dispositivi che non sono supportati dall'infrastruttura di gestione dinamica dei device node. Il bootscript poi avvia il demone Udev, udevd, il quale agirà in base agli uevent che riceve. Infine, il bootscript forza il kernel a replicare gli uevent per ciascun dispositivo che è già stato registrato e poi aspetta udevd che li gestisca.

7.4.2.3. Creazione dei Device Node

Per ottenere i corretti numeri major e minor di un dispositivo, Udev fa affidamento sull'informazione fornita da sysfs dentro /sys. Per esempio, /sys/class/tty/vcs/dev contiene la stringa «7:0». Questa stringa è usata da udevd per creare un device node con numero major 7 e minor 0. I nomi e i permessi dei nodi creati sotto la directory /dev sono determinati da regole specificate nei file dentro la directory /etc/udev/rules.d/. Questi sono numerati in una maniera simile al pacchetto LFS-Bootscripts. Se udevd non può trovare una regola per il dispositivo lo crea, esso avrà permessi di default a 660 e il proprietario a root:root. La documentazione della sintassi dei file di configurazione delle regole di Udev è in /usr/share/doc/udev-096/index.html

7.4.2.4. Caricamento dei Moduli

I driver dei device compilati come moduli possono avere inclusi degli alias. Gli alias sono visibili nell'output del programma modinfo e sono di solito associati agli identificativi dei dispositivi specifici del bus, supportati dal modulo. Per esempio, il driver snd-fm801 supporta dispositivi PCI con vendor ID 0x1319 e device ID 0x0801, e ha un alias «pci:v00001319d00000801sv*sd*bc04sc01i*». Per la maggior parte dei dispositivi, il driver bus esporta l'alias del driver che gestirebbe il dispositivo via sysfs. Es., il file /sys/bus/pci/devices/0000:00:0d.0/modalias può contenere la stringa «pci:v00001319d00000801sv00001319sd00001319bc04sc01i00». Le regole che LFS installa faranno sì che udevd chiami /sbin/modprobe con i contenuti della variabile d'ambiente uevent MODALIAS (che dovrebbe essere lo stesso del contenuto del file modalias dentro sysfs), caricando in questo modo tutti i moduli i cui alias corrispondono con la stringa dopo l'espansione del metacarattere.

In questo esempio, questo significa che, in aggiunta a snd-fm801, l'obsoleto (e indesiderato) driver forte sarà caricato se è disponibile. Guardare sotto per i modi in cui il caricamento dei driver indesiderati possono essere prevenuti.

Il kernel per se stesso è anche capace di caricare moduli per i protocolli di rete, filesystem e supporto a NLS su richiesta.

7.4.2.5. Gestione delle periferiche dinamiche e hotplug

Quando si collega una periferica, come un lettore MP3 USB (Universal Serial Bus), il kernel riconosce che la periferica è ora collegata e genera un evento hotplug. Questo uevent viene poi gestito da udevd come descritto sopra.

7.4.3. Problemi legati al caricamento dei moduli e alla creazione di dispositivi

Ci sono alcuni problemi conosciuti quando si creano automaticamente dei device node.

7.4.3.1. Un modulo del kernel non viene caricato automaticamente

Udev caricherà un modulo solamente se esso ha un alias specifico del bus e il driver del bus abbia propriamente esportato l'alias necessario in sysfs. Negli altri casi, si dovrebbe organizzare il caricamento del modulo attraverso altri mezzi. Con Linux-2.6.16.27, Udev è conosciuto caricare driver propriamente scritti per dispositivi INPUT, IDE, PCI, USB, SCSI, SERIO e FireWire.

Per determinare se il driver del dispositivo che si richiede abbia il necessario supporto per Udev, eseguire modinfo con il nome del modulo come argomento. Adesso provare a localizzare la directory del dispositivo sotto /sys/bus e controllare se lì c'è un file modalias.

Se esiste il file modalias in sysfs, il driver supporta il dispositivo e può comunicare con esso direttamente, ma se non ha l'alias, questo è un bug nel driver. Caricare il driver senza l'aiuto di Udev e aspettare che il problema sia risolto successivamente.

Se non c'è il file modalias dentro la relativa directory sotto /sys/bus, questo significa che gli sviluppatori del kernel non hanno ancora aggiunto il supporto modalias a questo tipo di bus. Con Linux-2.6.16.27, è questo il caso con i bus ISA. Aspettare che questo problema sia risolto nelle successive versioni del kernel.

Udev non è affatto pensato per caricare driver «wrapper» come snd-pcm-oss e driver non-hardware come loop.

7.4.3.2. Un modulo del kernel non viene caricato automaticamente, e Udev non è fatto per caricarlo

Se il modulo «wrapper» migliora soltanto la funzionalità fornita da alcuni altri moduli (es., snd-pcm-oss migliora la funzionalità di snd-pcm rendendo la scheda audio disponibile alle applicazioni OSS), configurare modprobe per caricare il wrapper dopo che Udev abbia caricato il modulo wrapped. Per fare questo, aggiungere una riga «install» dentro /etc/modprobe.conf. Per esempio:

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

Se il modulo in questione non è un wrapper e è utile per se stesso, configurare il bootscript S05modules per caricare questo modulo all'avvio del sistema. Per fare questo, aggiungere il nome del modulo al file /etc/sysconfig/modules su una riga separata. Questo funziona anche per i moduli wrapper, ma in questi casi sarebbe sottoottimizzato.

7.4.3.3. Udev carica alcuni moduli indesiderati

O non compilare il modulo, o porlo nella blacklist dentro il file /etc/modprobe.conf come fatto con il modulo forte nell'esempio di seguito:

blacklist forte

I moduli posti nella Blacklist possono ancora essere caricati manualmente con il comando esplicito modprobe.

7.4.3.4. Udev crea un dispositivo non correttamente, o crea un symlink sbagliato

Questo di solito accade se una regola si combina con un dispositivo in modo inaspettato. Per esempio, una regola mal scritta può combinarsi sia con un disco SCSI (come desiderato) e sia con il corrispondente driver generico SCSI (non correttamente) del commerciante. Trovare la regola dannosa e renderla più specifica.

7.4.3.5. Regola Udev non funziona in modo affidabile

Questo può essere un'altra manifestazione del precedente problema. Se no, e la propria regola usa gli attributi di sysfs, può essere un problema di sincronizzazione, da correggere nei prossimi kernel. Per adesso, si può lavorare intorno ad esso creando una regola che aspetta l'attributo utilizzato di sysfs e lo appende al file /etc/udev/rules.d/10-wait_for_sysfs.rules. Pregasi informare la lista LFS Development se si fa così e questo è di aiuto.

7.4.3.6. Udev non crea un dispositivo

Un ulteriore testo suppone che il driver sia compilato staticamente nel kernel o sia già caricato come modulo, e che si sia già controllato che Udev non abbia creato un dispositivo malnominandolo.

Udev non ha informazioni necessarie per creare un device node se un driver del kernel non ha esportato i propri dati in sysfs. Questo è più comune con driver di terze parti al di fuori dell'albero del kernel. Creare un device node statico in /lib/udev/devices con gli approriati numeri major/minor (vedere il file devices.txt dentro la documentazione del kernel o la documentazione fornita dal comerciale del driver di terze parti). Il device node statico sarà copiato in /dev dal bootscript S10udev.

7.4.3.7. L'ordine di nomenclatura dei dispositivi cambia casualmente dopo il riavvio

Questo è dovuto al fatto che Udev, per progetto, gestisce uevent e carica i moduli in parallelo, e pertanto in un ordine imprevedibile. Questo non sarà mai «corretto». Non si dovrebbe far affidamento sul fatto che i nomi dei dispositivi del kernel diventino stabili. Invece, creare le proprie regole in modo tale che facciano dei symlink con dei nomi stabili basati su alcuni attributi stabili del dispositivo, come un numero seriale o l'output delle varie utility *_id installate da Udev. Vedere Sezione 7.12, «Creazione personalizzata di link simbolici ai dispositivi» e Sezione 7.13, «Configurazione dello script di rete» per degli esempi.

7.4.4. Letture Utili

Documentazione utile aggiuntiva è disponibile ai seguenti siti: