[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [volume] [parte]


Capitolo 76.   File di dispositivo

Nei sistemi Unix, come GNU/Linux, il kernel permette alle applicazioni di comunicare con le unità fisiche, ovvero i dispositivi, attraverso un'astrazione costituita dai file di dispositivo. Questi file sono di tipo speciale e tradizionalmente sono contenuti all'interno della directory /dev/.(1)

La particolarità di questi file sta nella definizione di due numeri, che in pratica costituiscono il canale di comunicazione con il kernel stesso. Si tratta del numero primario e del numero secondario (oppure major e minor, secondo la terminologia originale inglese), dove il primo rappresenta il tipo di dispositivo e il secondo serve a identificare esattamente un dispositivo particolare. Questi numeri dipendono dal kernel e di conseguenza possono variare da un sistema operativo Unix all'altro. Anche i nomi che si danno a questi file possono variare da un sistema Unix all'altro; in certi casi ci sono piccole differenze anche tra le stesse distribuzioni GNU/Linux. In ogni caso, il documento di riferimento per ciò che riguarda GNU/Linux, è il file sorgenti_linux/Documentation/devices.txt, corrispondente a Linux allocated devices, aggiornato da H. Peter Anvin.

Dal momento che questi file servono solo in quanto contengono i numeri primario e secondario di un certo dispositivo, potrebbero funzionare anche collocati al di fuori della loro directory tradizionale, utilizzando eventualmente nomi differenti. Questa possibilità viene sfruttata da alcune distribuzioni GNU/Linux, nella fase di installazione, quando nei dischetti di avvio vengono creati al volo i file di dispositivo necessari a completare l'operazione, utilizzando eventualmente la directory temporanea per questo scopo.

I file di dispositivo si distinguono in due categorie, in base al fatto che l'hardware a cui corrispondono sia in grado di gestire un flusso di caratteri (ma forse è più corretto usare il termine byte in questo caso), presi ognuno singolarmente, oppure richieda che i dati siano raggruppati in blocchi di una dimensione determinata. Nel primo caso si parla di dispositivo a caratteri, mentre nel secondo di dispositivo a blocchi.

Dato che i dispositivi fisici sono gestiti attraverso questi file di dispositivo, l'accesso all'hardware viene controllato con i permessi che vengono dati a questi file. La gestione di questi permessi è molto importante nell'impostazione che viene data al sistema ed è uno dei punti su cui si trovano le differenze significative tra le varie distribuzioni GNU/Linux. Inoltre, l'esistenza di utenti e gruppi fittizi, con nomi come floppy, sys, daemon e altri, dipende spesso da questa esigenza di controllo dell'accesso ai dispositivi.

76.1   Directory «/sys/»

A partire dai kernel Linux 2.6.* viene introdotto un file system virtuale che deve essere innestato nella directory /sys/, predisponendo nel file /etc/fstab la direttiva seguente:

...
sys   /sys           sysfs  defaults  0  0
...

In questo modo, quando si avvia un sistema GNU/Linux, all'interno di questa directory /sys/ appaiono una serie di informazioni sui dispositivi fisici esistenti e sui moduli del kernel che sono in funzione. Delle informazioni contenute in questa directory si avvale, per esempio, il sistema uDev per la creazione automatica dei file di dispositivo.

76.2   Creazione dei file di dispositivo

Quando si ricompila il kernel per includere la gestione di funzionalità particolari, per accedere a queste, o per accedere ai componenti fisici per i quali è stata stabilita la gestione, può essere necessario intervenire nella directory /dev/ allo scopo di creare o modificare qualche file di dispositivo. In generale, le distribuzioni GNU/Linux tendono a prevedere tutti i file necessari, ma la stessa evoluzione del kernel introduce esigenze nuove e spesso la necessità di provvedere da soli a questi file. Inoltre, è difficile che siano disponibili dal principio tutti i file di dispositivo possibili e immaginabili.

I file di dispositivo si creano in particolare con il programma di servizio mknod:

mknod [-m modalità_dei_permessi] file {b|c|u} [n_primario n_secondario]

Con la lettera «b» si crea un file di dispositivo a blocchi, mentre con la lettera «c», si crea un file di dispositivo a caratteri. Il caso particolare della lettera «u», riguarda un dispositivo a caratteri senza buffer.

Si osservino gli esempi seguenti:

Anche se mknod è tutto quello che serve per creare i file di dispositivo necessari, non è sempre il mezzo più comodo per provvedere a questo problema. Infatti, occorre considerare anche le convenzioni della propria distribuzione GNU/Linux, anche per ciò che riguarda i permessi e l'appartenenza di questi file; inoltre non è sempre detto che si possano ricordare esattamente le caratteristiche dei file di dispositivo di cui si ha bisogno. Per questo viene in aiuto lo script MAKEDEV, che tradizionalmente si deve trovare proprio nella directory /dev/. Questo script non è standard, ma il suo scopo lo è: facilitare la creazione dei file di dispositivo.

/dev/MAKEDEV {dispositivo...|gruppo}

Generalmente si possono indicare come argomento uno o più nomi di file di dispositivo, senza il percorso. Questi dovrebbero essere creati nella directory corrente. L'esempio seguente crea il file di dispositivo corrispondente alla prima console virtuale, assegnandogli tutti gli altri attributi corretti:

/dev/MAKEDEV tty1[Invio]

L'esempio successivo crea il file di dispositivo corrispondente al primo disco fisso ATA, assegnandogli tutti gli altri attributi corretti:

/dev/MAKEDEV hda[Invio]

È probabile che, al posto dei nomi dei file di dispositivo, si possano usare nomi di gruppi di questi. Per esempio, lo script MAKEDEV della distribuzione GNU/Linux Debian prevede il gruppo generic per fare riferimento ai file di dispositivo più comuni:

/dev/MAKEDEV generic[Invio]

76.3   kernel Linux e Devfs

Il kernel Linux, fino alle versioni 2.4.*, può essere predisposto per la gestione automatica dei file di dispositivo (sezione 72.2.20), attraverso quello che viene chiamato Devfs (letteralmente: Device file system). Se questa gestione è attivata in modo predefinito, oppure si utilizza l'opzione di avvio devfs=mount, nella directory /dev/ viene innestato un file system virtuale contenente tutti i file di dispositivo necessari alla gestione dell'hardware riconosciuto dal kernel.

I file di dispositivo generati automaticamente dal kernel sono organizzati in una struttura più articolata rispetto al solito, per ciò che riguarda i sistemi GNU/Linux; per esempio, il file di dispositivo che fa riferimento al primo disco ATA, che di solito è /dev/hda, con Devfs è invece /dev/ide/host0/bus0/target0/lun0/disk.

Dal momento che si tratta di un file system virtuale, generato in modo automatico, esistono due tipi di problemi: se si modificano i permessi o si creano dei collegamenti, queste modifiche valgono solo fino a che il sistema operativo rimane in funzione. Per ovviare a questo inconveniente e anche per dare la possibilità di ricreare, tramite collegamenti simbolici, la struttura consueta ai nomi dei file di dispositivo, viene in aiuto un programma demone, devfsd, che deve essere configurato in modo da sistemare i permessi come desiderato e ricostruire i collegamenti simbolici necessari.

Per la configurazione del demone devfsd sarebbe meglio affidarsi all'impostazione data nella propria distribuzione GNU/Linux, dal momento che è necessario predisporre un meccanismo che consenta ai pacchetti applicativi che lo richiedono, di aggiungere le particolarità loro necessarie. In generale, i file di configurazione in questione si articolano a partire da /etc/devfs/.

È bene riepilogare le opzioni di avvio del kernel che sono utili per controllare l'utilizzo o meno del file system Devfs:

Si osservi inoltre che, per sicurezza, la directory /dev/ può contenere ugualmente i file di dispositivo tradizionali, perché quando si attiva il file system Devfs il contenuto originale della directory viene oscurato. In altri termini, quando da un sistema organizzato con file di dispositivo tradizionali si passa all'uso di Devfs, inizialmente conviene lasciare la directory /dev/ come si trova, in modo da poter avviare sia con la gestione Devfs, sia senza.

Devfs è superato da uDev, nei kernel Linux 2.6.*: <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-FAQ>

76.4   kernel Linux e uDev

A partire dalle versioni 2.6.* del kernel Linux, il meccanismo Devfs per la gestione automatica dei file di dispositivo è considerato obsoleto, dove al suo posto si preferisce usare uDev, che non viene gestito direttamente dal kernel, ma da un programma esterno (il demone udevd).

Dal punto di vista del risultato, uDev si comporta in modo simile a Devfs.

Per poter funzionare, uDev si avvale delle informazioni fornite dal file system virtuale /proc/ e da /sys/ (il secondo viene introdotto a partire dai kernel 2.6.*). Perché il file system virtuale /sys/ venga innestato correttamente, occorre verificare che il file /etc/fstab contenga la dichiarazione appropriata, molto simile a quella del file system virtuale /proc/:

...
proc    /proc            proc    defaults         0   0
none    /proc/bus/usb    usbfs   defaults         0   0
sys     /sys             sysfs   defaults         0   0
...

L'esempio mostra anche gli altri file system virtuali comuni.

uDev utilizza alcuni file di configurazione che normalmente si collocano nella directory /etc/udev/. Il primo file da prendere in considerazione è /etc/udev/udev.conf, che di solito viene distribuito già configurato correttamente. Ecco un esempio del suo contenuto:

# udev.conf

# The initial syslog(3) priority: "err", "info", "debug" or its
# numerical equivalent. For runtime debugging, the daemons internal
# state can be changed with: "udevcontrol log_priority=<value>".
udev_log="err"

# maximum size of the /dev tmpfs
tmpfs_size="10M"

Per definire le caratteristiche dei file di dispositivo da creare, inclusi i loro permessi di accesso, si utilizzano i file contenuti nella directory /etc/udev/rules.d/, che vengono «eseguiti» secondo l'ordine lessicografico del loro nome. Per questo, di norma si tratta di collegamenti simbolici a file contenuti nella directory /etc/udev/, che però hanno nomi che non tengono conto dell'ordine di esecuzione.

La sintassi con cui sono definite le direttive all'interno dei file a cui si fa riferimento nella directory /etc/udev/rules.d/ è piuttosto oscura, anche se si può intuire il senso di ciò che rappresenta. Per intervenire in qualche modo nei file di dispositivo, attraverso la gestione di uDev, bisognerebbe creare un proprio file, scegliendo un nome appropriato alla posizione in cui deve trovarsi nella sequenza di esecuzione. Tuttavia, ci sarebbe anche la possibilità di usare il file /etc/udev/links.conf per cose molto semplici: creazione di collegamenti simbolici, directory e file di dispositivo particolari. L'uso di questo file viene sconsigliato, ma è bene sapere come si interpreta, se dovesse essercene uno predefinito.

# This file does not exist. Please do not ask the debian maintainer about it.
# You may use it to do strange and wonderful things, at your risk.

L fd            /proc/self/fd
L stdin         /proc/self/fd/0
L stdout        /proc/self/fd/1
L stderr        /proc/self/fd/2
L core          /proc/kcore
L sndstat       /proc/asound/oss/sndstat

D pts
D shm

M null          c   1 3
M console       c   5 1

# Hic sunt leones.
M ppp           c 108 0
D loop
M loop/0        b   7 0
D net
M net/tun       c  10 200

L'esempio appena mostrato dovrebbe essere abbastanza intuitivo: le righe che iniziano con la lettera «L» richiedono la creazione di un collegamento simbolico (link); le righe che iniziano con la lettera «D» richiedono la creazione di una directory; le righe con la lettera «M» richiedono la creazione di un file di dispositivo.

Per quanto riguarda l'avvio e l'arresto del demone udevd, è auspicabile che la propria distribuzione GNU/Linux sia già organizzata per questo. A ogni modo, si intuisce che questo demone deve essere avviato molto presto nell'ambito della procedura di avvio del sistema e deve anche essere fermato solo alla fine della procedura di arresto.

Dal momento che uDev è un sistema esterno al kernel, durante la fase di avvio, c'è sicuramente un momento in cui il kernel ha innestato il file system principale, ma uDev non è ancora in funzione. Per questa ragione, è indispensabile che la directory /dev/, contenga inizialmente i file di dispositivo comuni, altrimenti diventa praticamente impossibile avviare il sistema.

Successivamente, una volta attivato uDev, il contenuto della directory /dev/ originale diventa accessibile a partire da /dev/.static/dev/, dove è possibile intervenire per modificare i file di dispositivo statici iniziali.

76.4.1   Associare un'azione agli eventi di uDev

I file contenuti nella directory /etc/udev/rules.d/ consentono di associare un'azione agli eventi di uDev. Per esempio, alla comparsa di un file di dispositivo è possibile associargli la modifica dei permessi, ma si arriva anche a poter associare l'avvio di un processo che abbia qualcosa a che fare con questo.

A titolo di esempio, si supponga di voler attribuire i permessi di lettura e scrittura, per tutti gli utenti, ai file di dispositivo che hanno a che fare con la gestione dell'audio, ai file relativi a dischetti e CD/DVD-ROM. Si comincia esplorando la situazione della directory /etc/udev/rules.d/:

ls /dev/udev/rules.d[Invio]

...
020_permissions.rules
025_libgphoto2.rules
025_libsane.rules
85-pcmcia.rules
udev.rules
z20_persistent-input.rules
z20_persistent.rules
z25_persistent-net.rules
z45_persistent-net-generator.rules
z50_run.rules
z55_hotplug.rules
z60_hdparm.rules
z60_xserver-xorg-input-wacom.rules
...

Tra le direttive di questi file, ci potrebbero essere già quelle che si prendono cura dei file di dispositivo a cui si è interessati. Ma per questo, conviene aggiungere un altro file, in modo che appaia per ultimo, secondo l'ordine lessicografico. Per esempio: z90_permessi-a-tutti.rules. Il file in questione potrebbe essere realizzato nel modo seguente:

ACTION=="add", SUBSYSTEM=="sound",                                          MODE="0666"
ACTION=="add", SUBSYSTEM=="block", KERNEL=="fd[0-9]*",                      MODE="0666"
ACTION=="add", SUBSYSTEM=="block", KERNEL=="hd[a-z]", DRIVERS=="ide-cdrom", MODE="0666"

Intuitivamente si comprende che le direttive di questi file sono composte da un elenco di attributi che servono a identificare i file di dispositivo a cui si è interessati e l'evento considerato, seguito dall'azione da compiere. In questo caso, l'azione da compiere è rappresentata dalla voce MODE="0666", che attribuisce i permessi di lettura e scrittura a tutti gli utenti.

Per vedere come si associa l'esecuzione di un programma a un evento dei file di dispositivo, si pensi a una stampante collegata attraverso una porta USB: quando si collega la stampante viene creato automaticamente il file di dispositivo /dev/usb/lp0, mentre quando la si stacca, questo file viene eliminato. Se si usa un demone per il servizio di stampa che non è preparato per queste sorprese, occorre aggiungere un altro file con delle direttive appropriate. Per esempio potrebbe trattarsi del file z90_stampante-usb.rules:

#
# Reload "lpd" when adding a printer.
#
ACTION=="add",    SUBSYSTEMS=="usb", KERNEL=="lp[0-9]*", RUN+="/etc/init.d/lpd restart"
#
# Reload "lpd" when removing a printer.
#
ACTION=="remove", SUBSYSTEMS=="usb", KERNEL=="lp[0-9]*", RUN+="/etc/init.d/lpd restart"
#

In pratica, in questo esempio si fa in modo che venga eseguito il comando /etc/init.d/lpd restart quando ci sono novità sui file di dispositivo per la stampa.

Si osservi che le direttive riferite a eventi di creazione dei file di dispositivo (ACTION="add") devono precedere quelle riferite a eventi di eliminazione degli stessi (ACTION="remove").

È importante osservare che i programmi o gli script che si avviano attraverso la gestione degli eventi di uDev non possono essere troppo impegnativi, altrimenti c'è il rischio di bloccare il sistema.

76.5   Messaggio: «unable to open an initial console»

Quando si utilizzano dei meccanismi automatici per la gestione dei file di dispositivo, può succedere che qualcosa non funzioni nel modo previsto. In particolare, può capitare che all'avvio il kernel non riesca a trovare il file di dispositivo /dev/console, cosa che si traduce nel messaggio di avvertimento seguente:

...
Warning: unable to open an initial console
...

Per poter comprendere cosa accade, è necessario avviare il sistema attraverso un disco esterno (dischetti di avvio di emergenza, CD/DVD autoavviabili o simili), con il quale si può indagare sullo stato iniziale della directory /dev/ (si intende la directory /dev/ del file system che è in funzione quando si tenta di avviare il sistema operativo senza successo). Se questa è vuota, come può succedere se ci si affida a uDev o a Devfs, conviene predisporre manualmente dei file di dispositivo al suo interno, che vengono utilizzati in mancanza del funzionamento (tempestivo) dei sistemi automatici.

Se si dispone dello script MAKEDEV, dovrebbe essere sufficiente il comando seguente, da eseguire quando la directory corrente corrisponde alla directory dev/ che si intende sistemare:

./MAKEDEV generic[Invio]

Naturalmente, se lo script MAKEDEV non si trova nella stessa directory, ma altrove, si deve specificare il percorso di avvio appropriato.

Appunti di informatica libera 2007.02 --- Copyright © 2000-2007 Daniele Giacomini -- <daniele (ad) swlibero·org>


1) L'argomento dei file speciali, compresi quelli che rappresentano i dispositivi, viene trattato nel capitolo 181 capitolo. Tuttavia, è necessario anticipare il problema, dal momento che è connesso strettamente alla creazione di kernel personalizzato.


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome file_di_dispositivo.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico]

Valid ISO-HTML!

CSS validator!