Device File System Guide
1.Cos'è devfs?
I (bei?) vecchi tempi
Attenzione: devfs è obsoleto e potrà essere rimosso dall'albero 2.6
del kernel stabile. Utenti di kernel 2.6 sono avvisati di passare a udev. Per
maggiori informazioni fare riferimento alla Guida Gentoo a udev
|
Implementazioni tradizionali di Linux provvedono ai loro
utenti un percorso astratto dei dispositivi, chiamato /dev.
In questa directory, gli utenti possono trovare i device nodes,
file speciali che rappresentano le periferiche presenti nei
loro sistemi. Per intenderci, /dev/hda rappresenta
la prima periferica IDE del nostro sistema. Attraverso questi
file di periferica, gli utenti possono creare programmi che interagiscono
con l'hardware come se fosse un file regolare invece che attraverso
speciali API.
I file di periferica sono suddivisi in due gruppi chiamati
periferiche a caratteri (character devices) e periferiche a blocchi (block devices). Il primo gruppo racchiude l'hardware la cui
scrittura/lettura non è bufferizzata. Il secondo gruppo, quindi,
racchiude invece l'hardware la cui scrittura/lettura è bufferizzata.
Le periferiche di ambedue i gruppi possono leggere un carattere alla volta o
in blocchi. Per questo, la nomenclatura potrebbe confondere ed infatti
non è corretta.
Se date un'occhiata a certi file di periferica, potreste trovare
qualcosa del genere:
Esempio 1: Controllare le informazioni di un file di periferica |
# ls -l /dev/hda
brw-rw---- 1 root disk 3, 0 Jul 5 2000 /dev/hda
|
Nell'esempio precedente abbiamo visto che /dev/hda
è una periferica a blocchi (block device). Rivestono molta
importanza i due numeri speciali assegnati al file di periferica:
3,0. Questa coppia di numeri è chiamata
major-minor ed è usata dal kernel per mappare un
file di periferica al dispositivo reale. Il major corrisponde a
certi dispositivi mentre il minor a sotto dispositivi.
Due esempi sono /dev/hda4 e /dev/tty5.
Il primo file di periferica corrisponde alla quarta partizione della
prima periferica IDE. La sua coppia major-minor è 3, 4.
In altre parole, il minor corrisponde alla partizione dove il
major corrisponde alla periferica. Il secondo esempio ha 4, 5 come coppia major-minor.
In questo caso, il major corrisponde ad un terminal driver, mentre
il minor corrisponde al numero del terminale (in questo caso, al
quinto terminale).
I problemi
Se fate un rapido controllo in /dev, troverete
che sono listate non solo le vostre periferiche, ma tutte
le possibili periferiche voi possiate immaginare. In altre parole,
sono presenti file di periferica anche per i dispositivi
non presenti sul vostro sistema.
Il controllo di un numero così elevato di gruppi di periferiche è quanto mai
difficoltoso. Immaginate di dover cambiare i permessi di tutti i
file di periferica che hanno un corrispondente dispositivo sul vostro sistema,
e lasciare il resto invariato.
Quando aggiungete nuovo hardware al vostro sistema che non ha
un file di periferica per il nuovo dispositivo, dovrete crearne uno. Utenti esperti sanno che
questo può essere fatto con ./MAKEDEV all'interno
della directory /dev, ma dovete conoscere quale dispositivo creare.
Quando avete programmi che interagiscono con hardware usando
i file di periferica, non potete avere la partizione principale montata
in sola lettura, mentre non c'è ulteriore necessità di averla
montata in lettura-scrittura. E non potete avere /dev
su una partizione separata, dato che mount necessita
di /dev per montare le partizioni.
Le soluzioni
Come potete immaginare, gli sviluppatori del kernel hanno
trovato un certo numero di soluzioni ai summenzionati problemi.
Comunque molte di queste presentano altri difetti come descritto in
http://www.atnf.csiro.au/people/rgooch/linux/docs/devfs.html#faq-why.
Non faremo una panoramica su queste implementazioni, ma ci
focalizzeremo su quella che è diventata parte dei sorgenti
ufficiali del kernel: devfs.
devfs vince completamente
devfs risolve tutti i problemi elencati. Provvede solo
le periferiche esistenti, aggiunge nuovi nodi quando trova
nuove periferiche e rende possibile montare il root
filesystem in sola lettura. Risolve anche altri problemi
che non abbiamo discusso perché di minore interesse per
gli utenti.
Inoltre, con devfs non dobbiamo preoccuparci della
coppia major/minor. E' ancora supportata (per
compatibilità all'indietro), ma non è necessaria.
Questo rende possibile per Linux il supporto di
ancora più periferiche, dato che non ci sono più
limiti (i numeri hanno sempre dei confini :)
Anche devfs ha i propri problemi che per gli utenti finali
non sono realmente visibili, ma lo sono per i manutentori
del kernel. E per loro sono talmente gravi che hanno marcato
devfs come obsoleto in favore di udev
che Gentoo supporta e usa come default su molte architetture a partire dalla
release 2005.0 usando kernel della serie 2.6.
Per avere maggiori informazioni sul perché devfs è marcato come obsoleto,
potete leggere queste
udev
FAQ e il documento udev contro devfs.
2.Navigare attraverso l'albero dei device
Directory
Una delle prime cose che potreste notare è che devfs usa
directory per raggruppare insieme le periferiche.
Questo migliora la leggibilità dato che tutte le periferiche
dello stesso tipo occupano la stessa directory.
Per intenderci, tutte le periferiche IDE sono all'interno
della directory /dev/ide/, così come tutte
le periferiche SCSI sono in /dev/scsi/.
Dischi SCSI e IDE sono visti nello stesso modo, il che
significa che entrambe hanno la stessa struttura di
sottodirectory.
Dischi IDE e SCSI sono controllati da un adattatore
(integrato su scheda madre o su schede separate),
chiamato host.
Ogni adattatore può avere diversi canali. Un canale
è chiamato bus. Su ogni canale, è possibile
avere diversi ID. Ogni ID identifica un disco.
Questo ID è chiamato target. Alcuni device
SCSI possono avere lun multipli (Logial Unit Numbers),
device che possono controllare multipli media simultaneamente
(hi-end tapedrive). Voi avrete principalmente
un singolo lun, lun0/.
Così, mentre prima avevamo /dev/hda4, ora
abbiamo /dev/ide/host0/bus0/target0/lun0/part4.
Questo è molto più semplice... no, non discutete con me...
è semplice...
Nota:
Potete anche usare una nomenclatura più Unix-like per
gli hard disk, come c0b0t0u0p2. Possono
essere trovati in /dev/ide/hd, /dev/scsi/hd, ecc.
|
Per darvi un'idea delle directory, questa è una lista
delle directory che ho sul mio portatile:
Esempio 2: Directory in /dev |
cdroms/ cpu/ discs/ floppy/
ide/ input/ loop/ misc/
netlink/ printers/ pts/ pty/
scsi/ sg/ shm/ sound/
sr/ usb/ vc/ vcc/
|
Compatibilità all'indietro usando devfs
Usare questo nuovo schema sembra divertente, ma alcuni tools
e programmi continuano ad usare il vecchio schema.
Per assicurare la compatibilità è stato creato devfsd.
Questo daemon crea link simbolici con i vecchi nomi che puntano
ai nuovi file di periferica.
Esempio 3: Link simbolico |
$ ls -l /dev/hda4
lr-xr-xr-x 1 root root 33 Aug 25 12:08 /dev/hda4 -> ide/host0/bus0/target0/lun0/part4
|
Con devfsd, potete anche configurare i permessi, creare
nuovi device file, definire azioni, ecc. Tutto questo è descritto
nel prossimo capitolo.
3.Amministrare l'albero dei dispositivi
Riavvio di devfsd
Quando modificate il file /etc/devfsd.conf,
e volete forzare queste modifiche nel vostro sistema,
non dovete riavviare la macchina. A seconda delle vostre
necessità, potete usare uno dei seguenti segnali:
SIGHUP forzerà devfsd a rileggere il file
di configurazione, ricaricare gli oggetti condivisi e generare
il REGISTER degli eventi per ogni nodo in vita
nell'albero dei dispositivi.
SIGUSR1 come il precedente, ma non verrà rigenerato
il REGISTER degli eventi.
Per inviare un segnale, usate semplicemente kill
o killall:
Esempio 4: Inviare un segnale SIGHUP a devfsd |
# kill -s SIGHUP `pidof devfsd`
# killall -s SIGHUP devfsd
|
Rimuovere la compatibilità attraverso i symlink
Attenzione:
Attualmente, Gentoo non può vivere senza la compatibilità
attraverso i symlink.
|
Se volete rimuovere la compatibilità ottenuta con la creazione
dei numerosi symlink in /dev dal vostro
sistema Gentoo (dato che Gentoo attiva la compatibilità di default),
editate /etc/devfsd.conf e rimuovete le seguenti
due righe:
Esempio 5: /etc/devfsd.conf per la compatibilità all'indietro |
REGISTER .* MKOLDCOMPAT
UNREGISTER .* RMOLDCOMPAT
|
Dovrete quindi riavviare il vostro sistema per rendere attive
le modifiche.
Rimuovere la funzionalità di auto caricamento
Quando caricate un modulo, devfs creerà automaticamente un
file di periferica. Se non volete questo comportamento, rimuovete
la seguente riga da /etc/devfsd.conf:
Esempio 6: /etc/devfsd.conf, funzionalità autoload |
LOOKUP .* MODLOAD
|
4.Punti riguardanti i permessi
Impostare/cambiare i permessi con devfsd
Nota:
Queste istruzioni sono valide finché pam_console è disabilitato
in
/etc/pam.d/system-auth. Se pam_console viene abilitato,
PAM ha l'ultima parola sui permessi.
|
Se realmente volete impostare i permessi attraverso
/etc/devfsd.conf, usate la sintassi
del seguente esempio:
Esempio 7: Permessi in /etc/devfsd.conf |
REGISTER ^cdroms/.* PERMISSIONS root.cdrom 0660
|
Il secondo campo è il gruppo di dispositivi, partendo da /dev.
E' un'espressione regolare attraverso la quale potete
selezionare diversi file di periferica con una sola regola.
Il quarto campo è il proprietario del file di periferica.
Il quinto campo contiene i permessi del file di periferica.
Impostare i permessi manualmente e farli salvare a devfsd
Questo è ciò che Gentoo fa di default: se
cambiate proprietario (con chown) e permessi
(con chmod) di alcuni file di periferica, devfsd
salverà le informazioni in modo tale da renderle persistenti
ad ogni riavvio del sistema. Questo perché il file /etc/devfsd.conf
contiene le seguenti righe:
Esempio 8: /etc/devfsd.conf per il salvataggio dei permessi |
REGISTER ^pt[sy]/.* IGNORE
CHANGE ^pt[sy]/.* IGNORE
CREATE ^pt[sy]/.* IGNORE
DELETE ^pt[sy] IGNORE
REGISTER ^log IGNORE
CHANGE ^log IGNORE
CREATE ^log IGNORE
DELETE ^log IGNORE
REGISTER .* COPY /lib/dev-state/$devname $devpath
CHANGE .* COPY $devpath /lib/dev-state/$devname
CREATE .* COPY $devpath /lib/dev-state/$devname
DELETE .* CFUNCTION GLOBAL unlink
/lib/dev-state/$devname
RESTORE /lib/dev-state
|
In altre parole, le modifiche ai file di periferica sono copiate
in /lib/dev-state non appena avviene il cambiamento
e ripristinate in /dev all'avvio
del sistema.
Un'altra possibilità è di montare /lib/dev-state
in /dev al momento dell'avvio. Per fare questo
dovete essere sicuri che devfs non venga montato automaticamente
(il che significa che dovrete ricompilare il kernel) e
che esista /dev/console.
Quindi, da qualche parte all'inizio degli script di avvio
del vostro sistema, dovete mettere:
Esempio 9: Montare /lib/dev-state in /dev |
mount --bind /dev /lib/dev-state
mount -t devfs none /dev
devfsd /dev
|
5.Risorse
Per maggiori informazioni su devfs, controllate le seguenti
risorse.
Le manpage di devfsd.conf spiegano la sintassi
del file /etc/devfsd.conf.
Per vederle, digitate man devfsd.conf.
Le devfs FAQ spiegano tutto ciò che riguarda devfs.
Contengono anche informazioni sulla struttura interna
dei devfs e come i driver possono supportare devfs.
Su LinuxJournal
c'è un interessante articolo su devfs for
Management and Administration.
Daniel Robbins ha scritto una serie di articoli per
IBM's DeveloperWorks sui filesystem avanzati.
Tre di questi riguardano devfs:
|