[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]


22. Moduli

Quando si ha una certa dimestichezza con la ricompilazione del kernel, si potrebbe considerare l'utilizzo dei moduli come una complicazione inutile. Tuttavia, ci sono situazioni in cui l'uso dei moduli è una necessità, prima tra tutte l'installazione di GNU/Linux attraverso le distribuzioni che fanno uso di moduli per ottenere un dischetto di avvio unico, oppure per ridurne la scelta a pochi. D'altro canto, la conoscenza dei meccanismi legati alla gestione dei moduli del kernel è utile per sfruttare un sistema già ben organizzato dalla propria distribuzione GNU/Linux.

Questo capitolo, pur trovandosi in una posizione iniziale di questo documento, non è rivolto ai principianti che potrebbero trovare alcuni punti particolarmente complessi (come il problema del disco RAM iniziale). Tuttavia, quando si installa GNU/Linux, potrebbe essere necessario conoscere l'uso dei parametri di alcuni moduli.

Nome Descrizione
insmod Carica manualmente i moduli del kernel.
rmmod Scarica manualmente i moduli del kernel.
lsmod Elenca i moduli caricati nel kernel.
depmod Rigenera il file delle dipendenze tra i moduli.
modprobe Carica un modulo rispettando le dipendenze.
/etc/conf.modules Configurazione dei moduli utilizzati.
kerneld Programma demone per il carico e lo scarico automatico dei moduli.

Tabella 22.1: Riepilogo dei programmi e dei file per la gestione dei moduli.

In questo capitolo vengono mostrati anche i parametri di alcuni tipi di moduli, mentre nel capitolo 23 ne sono riepilogati altri in modo sintetico.

22.1 Gestione dei moduli

I moduli del kernel sono porzioni di questo che possono essere caricate in memoria quando se ne presenta la necessità, e scaricate subito dopo. I moduli del kernel Linux sono quello che in altri sistemi viene definito driver. Nella sezione 20.1.2 è già stato descritto in che modo possa essere compilato un kernel di questo tipo, e anche come generare i moduli relativi.

Se si dispone di una distribuzione GNU/Linux organizzata con un kernel modulare, è consigliabile sfruttare quel kernel già predisposto, assieme ai suoi moduli.

22.1.1 Funzionamento in breve

Il minimo indispensabile per attivare e disattivare i moduli è costituito da due programmi di utilità specifici: `insmod' e `rmmod'. Il primo serve per caricare i moduli, il secondo per scaricarli.

L'operazione di caricamento dei moduli deve essere fatta tenendo presente le eventuali dipendenze che ci possono essere. Per esempio, se il modulo «C» richiede la presenza del modulo «B», il quale a sua volta richiede la presenza del modulo «A», occorre caricare ordinatamente i moduli «A», «B» e «C». Nello stesso modo, lo scarico dei moduli può essere fatto solo se si rispettano le dipendenze. Nel caso appena descritto, per scaricare il modulo «A» occorre prima scaricare «C» e «B».

22.1.2 Aspetto e collocazione

I moduli sono generalmente file che terminano con l'estensione `.o' e si collocano al di sotto della directory `/lib/modules/<versione>/', dove la versione si riferisce al kernel per il quale sono stati predisposti. Per esempio, `/lib/modules/2.0.33/', si riferisce ai moduli del kernel 2.0.33.

Per facilitare l'individuazione dei moduli, e quindi anche il loro caricamento, viene creato generalmente un file, `modules.dep', nella directory iniziale di questi, attraverso il programma `depmod'.

depmod -a

Generalmente questo comando viene inserito nella procedura di inizializzazione del sistema, in modo da aggiornare sistematicamente questo file.

Il file contiene l'elenco dei moduli presenti, con l'indicazione precisa delle dipendenze. L'esempio seguente mostra il caso del modulo della scheda di rete NE2000, `ne.o', il quale dipende dal modulo `8390.o'.

/lib/modules/2.0.33/net/ne.o: /lib/modules/2.0.33/net/8390.o

22.1.3 Caricamento guidato

Invece di caricare i moduli con il programma `insmod', che richiede attenzione nella sequenza di caricamento a causa delle dipendenze, si può utilizzare `modprobe' che si avvale del file `modules.dep' e si arrangia a caricare tutto quello che serve nel modo corretto. Per esempio, utilizzando il comando seguente,

modprobe ne

si ottiene prima il caricamento del modulo `8390.o' e successivamente di `ne.o'.

22.1.4 Parametri

Come accade già con i kernel monolitici, alcuni dispositivi possono essere individuati e gestiti correttamente solo se si forniscono delle informazioni aggiuntive. Per questo, alcuni moduli richiedono l'indicazione di parametri composti dalla sintassi

<simbolo>[=<valore>]

Quando si caricano i moduli di questo tipo con `insmod' è necessario fornire anche i parametri, nella parte finale della riga di comando. La stessa cosa vale per `modprobe', solo che in questo caso si può realizzare un file di configurazione, `/etc/conf.modules', contenente le informazioni sui parametri dei moduli utilizzati e altre indicazioni eventuali.

Per esempio, attraverso la riga seguente del file `/etc/conf.modules', si vuole specificare che l'indirizzo di I/O del dispositivo relativo al modulo `ne.o' è 0x300.

options ne io=0x0300 

22.1.5 Gestione automatica

Gli strumenti e la configurazione descritti nelle sezioni precedenti, possono essere gestiti in modo automatico attraverso il demone, `kerneld', oppure in modo integrato nei kernel 2.2.* (in questo caso si parla del thread `kmod').

Quando è utilizzato `kerneld', questo viene avviato generalmente dalla procedura di inizializzazione del sistema, dopo che è stato eseguito `depmod' per la rigenerazione del file delle dipendenze tra i moduli. Nel momento in cui il kernel ha bisogno di una funzione che non trova al suo interno, prova a interrogare `kerneld', il quale a sua volta di avvale di `modprobe' per il caricamento del modulo necessario. In questa situazione, il carico e lo scarico dei moduli in modo manuale non è più necessario: è `kerneld' che provvede. Ci possono essere comunque situazioni in cui il meccanismo non funziona, ma resta sempre la possibilità di usare `modprobe' in quei casi.

L'automazione della gestione dei moduli richiede che il file `/etc/conf.modules' sia configurato correttamente per quei dispositivi che si intendono usare.

Come accennato, i kernel 2.2.* incorporano `kmod' che si sostituisce alle funzionalità fondamentali di `kerneld'. In questo caso, si può osservare la presenza del file virtuale `/proc/sys/kernel/modprobe', il cui scopo è quello di informare il kernel sulla posizione in cui si trova il programma `modprobe'. Per questo, la procedura di inizializzazione del sistema dovrebbe provvedere a definirlo utilizzando un comando simile a quello seguente.

echo "/sbin/modprobe" > /proc/sys/kernel/modprobe

Dal momento che `kmod' non è efficiente quanto `kerneld', occorre provvedere (ammesso che lo si voglia) a eliminare periodicamente i moduli che non sono più utilizzati. Per farlo si può usare il sistema Cron attraverso una direttiva simile a quella seguente che si riferisce al file crontab dell'utente `root':

0-59/5 * * * * /sbin/rmmod -a

Nel caso si voglia utilizzare il file crontab di sistema, ovvero `/etc/crontab', la cosa cambia leggermente, come nell'esempio seguente:

0-59/5 * * * * root /sbin/rmmod -a

22.1.6 # insmod

insmod [<opzioni>] <file-oggetto> [<simbolo>=<valore>...] 

`insmod' permette di caricare un modulo nel kernel. Il nome del modulo può essere indicato specificando il nome del file completo di estensione ed eventualmente di percorso (path), oppure specificando semplicemente il nome del file del modulo senza l'estensione: in quest'ultimo caso, `insmod' cerca il file (con la sua estensione naturale) all'interno delle directory standard per i moduli.

Quando nel kernel è attivato il supporto del kernel daemon e il demone `kerneld' è in funzione, oppure si tratta di un kernel 2.2.* ed è disponibile `kmod', non dovrebbe essere necessario l'utilizzo di `insmod' per caricare i moduli.

Esempi

insmod /lib/modules/2.0.30/net/plip.o

Attiva il modulo `plip' rappresentato dal file `/lib/modules/2.0.30/net/plip.o'.

insmod plip

Come nell'esempio precedente, ma si lascia a `insmod' il compito di cercare il file.

22.1.7 # rmmod

rmmod [<opzioni>] <modulo>...

`rmmod' permette di scaricare uno o più moduli dal kernel, sempre che questi non siano in uso e non ci siano altri moduli caricati che vi fanno riferimento.

Nella riga di comando vengono indicati i nomi dei moduli e non i nomi dei file dei moduli. Se vengono indicati più moduli, questi vengono scaricati nell'ordine in cui appaiono.

Se viene usata l'opzione `-a', vengono scaricati tutti i moduli che risultano essere inattivi, senza bisogno di specificarli nella riga di comando.

Quando nel kernel è attivato il supporto del kernel daemon e il demone `kerneld' è in funzione, non dovrebbe essere necessario l'utilizzo di `rmmod' per scaricare i moduli. Se invece si utilizza un kernel 2.2.* con il supporto per `kmod', si deve provvedere periodicamente a eseguire il comando `rmmod -a'.

`rmmod' è in realtà solo un collegamento a `insmod' che quindi cambia il suo comportamento quando viene avviato utilizzando quel nome.

Esempi

rmmod plip

Scarica il modulo `plip'.

rmmod -a

Scarica tutti i moduli inutilizzati.

22.1.8 $ lsmod

`lsmod' permette di visualizzare la situazione sull'utilizzo dei moduli. Le stesse informazioni ottenibili da `lsmod' si possono avere dal contenuto del file `/proc/modules'. Utilizzando `lsmod' si ottiene una tabellina di tre colonne:

Esempi

Supponendo di avere appena caricato il modulo `plip' si può ottenere quanto segue:

lsmod[Invio]

Module         Pages    Used by
plip               3            0

22.1.9 # depmod

depmod [<opzioni>]

`depmod' serve a generare un file di dipendenze tra i moduli, che poi viene utilizzato da `modprobe' per caricarli rispettando le dipendenze. Precisamente, viene creato il file `/lib/modules/<versione>/modules.dep'.

Alcune opzioni

-a [<versione>] | --all [<versione>]

Scandisce tutti i moduli della versione del kernel in funzione. `depmod' viene utilizzato generalmente con questa opzione per creare il file delle dipendenze. Se si desidera creare il file delle dipendenze per i moduli di un altra versione di kernel, si può specificare espressamente tale versione.

-s | --system-log

Invia le segnalazioni di errore al registro del sistema.

Esempi

depmod -a

Genera il file `/lib/modules/<versione>/modules.dep'.

depmod -a 2.1.99

Genera il file `/lib/modules/2.1.99/modules.dep', riferito appunto ai moduli del kernel della versione 2.1.99.

---------

if [ -x /sbin/depmod ]
then
    echo "Analisi delle dipendenze tra i moduli"
    /sbin/depmod -a
fi

Si tratta di un pezzo di uno degli script della procedura di inizializzazione del sistema, in cui si avvia la generazione del file delle dipendenze tra i moduli solo se il programma esiste.

22.1.10 # modprobe

modprobe [<opzioni>] <file-oggetto> [<simbolo>=<valore>...] 

`modprobe' è un programma fatto per agevolare il caricamento dei moduli del kernel. Quando viene usato senza l'indicazione di alcuna opzione, cioè solo con il nome del modulo e l'eventuale aggiunta dei parametri, `modprobe' carica prima i moduli necessari a soddisfare le dipendenze, e solo dopo provvede al caricamento del modulo richiesto. Se l'operazione fallisce, tutti i moduli superflui vengono scaricati nuovamente.

Tra le altre cose, `modprobe' permette di tentare il caricamento del modulo «giusto» a partire da un gruppo, quando non si conosce bene quale sia il modulo adatto a un certo tipo di dispositivo o di servizio. Per farlo è necessario indicare il tipo di modulo e il modello. Il tipo è rappresentato dalla directory che lo contiene (`fs/', `misc/', `net/', `scsi/', ecc.) e il modello si esprime utilizzando i consueti caratteri jolly (`?' e `*').

`modprobe' fa uso di un file di configurazione, attraverso cui è possibile modificare le sue impostazioni predefinite, e in particolare si possono definire i parametri normali necessari ad alcuni tipi di moduli. Il file in questione è `/etc/conf.modules'.

Alcune opzioni

-a | --all

Carica tutti i moduli (generalmente non viene utilizzata questa opzione).

-c | --show-conf

Emette la configurazione attuale per la gestione dei moduli; ciò comprende sia la parte predefinita che il contenuto del file di configurazione (`/etc/conf.modules').

-l | --list

Elenca i moduli disponibili.

-r | --remove

Scarica i moduli dal kernel, eliminando anche quelli che erano stati caricati per soddisfare le dipendenze, sempre che ciò sia possibile.

-t <tipo> <modello> | --type <tipo> <modello>

Permette di definire il tipo di modulo, attraverso il nome usato per la directory che lo contiene (`fs/', `misc/', `net/', `scsi/',...) e attraverso un modello espresso con dei caratteri jolly. Utilizzando questa opzione, occorre fare attenzione a proteggere i caratteri jolly dall'interpretazione da parte della shell, per esempio con l'uso di apici singoli o doppi.

Esempi

modprobe -l

Elenca tutti i moduli disponibili.

modprobe -l -t net

Elenca tutti i moduli di tipo `net', cioè quelli contenuti nella directory omonima.

modprobe -l -t net '3c*'

Elenca i moduli il cui nome inizia per `3c', di tipo `net'; in pratica elenca i moduli delle schede di rete 3Com.

modprobe -c

Emette la configurazione attuale della gestione dei moduli `modprobe'.

modprobe plip

Carica il modulo `/lib/modules/<versione>/net/plip.o'.

modprobe -t net 'p*'

Tenta di caricare un modulo che inizi con la lettera `p', dalla directory `/lib/modules/<versione>/net/'.

22.1.11 # kerneld

kerneld [debug] [keep] [delay=<secondi>] [type=<numero-messaggio>] 

Nei kernel 2.0.*, `kerneld' è il demone che si occupa di gestire automaticamente i moduli, sempre che il kernel sia stato compilato in modo da includere questa possibilità di gestione automatizzata. `kerneld' viene attivato normalmente attraverso la procedura di inizializzazione del sistema, dopo che è stato rigenerato il file delle dipendenze tra i moduli. In pratica, l'avvio potrebbe avvenire nel modo seguente:

if [ -x /sbin/depmod ]
then
    echo "Analisi delle dipendenze tra i moduli"
    /sbin/depmod -a
fi

#...

if [ -x /sbin/kerneld ]
then
    echo "Avvio del demone per la gestione dei moduli"
    /sbin/kerneld
fi

Vedere eventualmente kerneld(1).

22.2 Configurazione dei moduli

Il file `/etc/conf.modules' permette di configurare il comportamento di `modprobe'. Le righe vuote e quanto preceduto dal simbolo `#' viene ignorato. Le righe possono essere continuate utilizzando la barra obliqua inversa (`\') alla fine, subito prima del codice di interruzione di riga.

Le righe di questo file vengono interpretate attraverso una shell, e questo permette di utilizzare le tecniche di sostituzione fornite comunemente da queste; per esempio con i caratteri jolly o con la sostituzione di comando.

Questo file di configurazione può contenere diversi tipi di direttive; nelle sezioni seguenti se ne mostrano solo alcune. Per la descrizione completa, si veda la pagina di manuale depmod(1).

In linea di massima, si possono accumulare più direttive dello stesso tipo.

22.2.1 alias

alias <alias> <modulo-reale>

La direttiva `alias' permette di indicare un nome alternativo a un nome di un modulo reale. Ciò può essere utile a vario titolo, e in ogni caso sono stabiliti molti alias già in modo predefinito. Lo si può osservare con il comando seguente:

modprobe -l[Invio]

...
# Aliases
alias binfmt-2 binfmt_aout
alias binfmt-0107 binfmt_aout
...
alias block-major-2 floppy
alias block-major-3 ide-probe
...
alias char-major-4 serial
alias char-major-5 serial
alias char-major-6 lp
...
alias dos msdos
...
alias iso9660 isofs
...
alias plip0 plip
alias plip1 plip
alias ppp0 ppp
alias ppp1 ppp
...

Per esempio, si può osservare che è possibile fare riferimento al modulo `isofs' anche attraverso il nome `iso9960'. Tuttavia, gli alias non sono semplicemente di aiuto agli «smemorati», ma anche una necessità. Si osservi la configurazione seguente tratta da un ipotetico file `/etc/conf.modules'.

alias eth0 ne
...

L'alias `eth0' (ovvero la prima interfaccia Ethernet) permette di fare in modo che quando si configura l'interfaccia di rete con `ifconfig', `kerneld' sappia quale modulo avviare: in questo caso `ne'.

Ogni modulo ha le sue particolarità, quindi deve essere valutata caso per caso l'opportunità di utilizzare un alias adatto a qualche scopo.

22.2.2 options

options <nome> <simbolo>=<valore>...

La direttiva `options' permette di definire i parametri di utilizzo di un modulo, identificato attraverso il suo nome reale, oppure attraverso un alias. Per esempio,

alias eth0 ne
options ne io=0x300 irq=11

definisce che il modulo `ne' (Ethernet NE2000) dovrà essere utilizzato per un dispositivo che si raggiunge con il canale di I/O 0x300 e l'IRQ 11.

Attraverso questa direttiva si indicano solo le opzioni che non possono essere determinate altrimenti dal sistema. Questo significa che non è necessaria una riga `options' per tutti i dispositivi che si intende utilizzare attraverso i moduli.

22.3 Avvio e initrd

Quando si realizza un kernel modulare standardizzato, si rischia di lasciare fuori dalla parte monolitica qualcosa che poi può rivelarsi indispensabile per l'avvio del sistema, prima di poter montare il filesystem principale.

Per fare un esempio concreto, basta pensare alla realizzazione di un kernel tuttofare per una distribuzione GNU/Linux. È impensabile che si realizzi un kernel in grado di montare il filesystem principale contenuto in un disco fisso SCSI. Infatti, per farlo, occorrerebbe che il codice per la gestione delle diverse schede SCSI esistenti fosse incorporato nel kernel di partenza, perché non ci sarebbe modo di accedere ai file dei moduli.

Si può risolvere il problema attraverso un disco RAM iniziale, o initrd, e naturalmente, il kernel deve essere in grado di montare un tale filesystem.

22.3.1 Disco RAM iniziale

Il metodo per realizzare un disco RAM iniziale è descritto nella documentazione allegata ai sorgenti del kernel: `/usr/src/linux/Documentation/initrd.txt'. In breve si tratta di predisporre un disco RAM con un filesystem Second-extended (Ext2) o Minix, contenente il minimo indispensabile per caricare i moduli necessari prima del montaggio del filesystem principale. Serviranno quindi i moduli e il programma `insmod'. A parte questo, serve una shell minima e le eventuali librerie.

Il disco RAM realizzato per questo scopo deve contenere il programma (o lo script) `/linuxrc', che verrà avviato appena montato il disco RAM. Generalmente, quando `/linuxrc' termina la sua esecuzione il disco RAM viene smontato.

Di solito, il disco RAM è un file compresso attraverso `gzip'. Per fare in modo che venga caricato all'avvio, occorre avvisare il kernel. Per Loadlin, LILO e SYSLINUX si può usare la direttiva seguente:

initrd=<file-initrd>

Naturalmente, nel caso di LILO la direttiva va collocata al di sotto di una dichiarazione `image'.

22.3.2 Un esempio

La distribuzione Red Hat, come altre, utilizza questa tecnica per avviare il modulo necessario alla gestione della scheda SCSI quando si dispone di un disco fisso SCSI contenente il filesystem principale. Il file del disco RAM viene collocato nella directory `/boot/'. Si tratta di un disco RAM in formato Second-extended, compresso con `gzip'. Per analizzarne il contenuto si deve decomprimere e montare come file-immagine.

cat /boot/initrd-2.0.33.img | gzip -d > /tmp/initrd.img

mount -o loop -t ext2 /tmp/initrd.img /mnt

La struttura seguente si riferisce al caso di un disco RAM iniziale per il caricamento del modulo `aic7xxx'.

.
|-- bin
|   |-- insmod
|   `-- sh
|-- dev
|   |-- console
|   |-- null
|   |-- ram
|   |-- systty
|   |-- tty1
|   |-- tty2
|   |-- tty3
|   `-- tty4
|-- etc
|-- lib
|   `-- aic7xxx.o
`-- linuxrc

Si può osservare l'assenza di librerie, ma questo è giustificato dal fatto che gli unici due programmi esistenti, `sh' e `insmod', sono in versione statica, cioè includono le librerie. Il file `/linuxrc' è uno script che si limita semplicemente a caricare il modulo già visto.

#!/bin/sh

insmod /lib/aic7xxx.o

22.4 Casi particolari

Il kernel è il risultato degli apporti di un gran numero di collaboratori, e non potrebbe essere altrimenti data la mole di lavoro che c'è dietro. Tenendo conto anche del fatto che i dispositivi hardware esistenti non sono tutti uguali, spesso è necessario annotare qualche trucco per riuscire a ottenere dei risultati particolari.

22.4.1 ne

Il modulo `ne' permette di gestire una scheda di rete NE2000 o NE1000, ma soltanto una. Se si dispone di due schede, è generalmente necessario compilare un kernel apposito e utilizzare un parametro di avvio adatto a farle riconoscere entrambe.

Con i moduli si può tentare di risolvere il problema facendo una copia del modulo e configurando i due moduli a seconda delle esigenze delle due schede. Nell'esempio si suppone di utilizzare il kernel 2.0.33.

cp /lib/modules/2.0.33/net/ne.o /lib/modules/2.0.33/net/ne2.o[Invio]

In tal modo si è ottenuta una copia del modulo. Adesso si dispone sia di `ne' che di `ne2'. Il file `/etc/conf.modules' andrà configurato opportunamente: si suppone che la prima scheda utilizzi l'indirizzo I/O 0x280 con l'IRQ 10, e che la seconda utilizzi l'indirizzo I/O 0x300 con l'IRQ 11.

alias eth0 ne
alias eth1 ne2
options ne io=0x280 irq=10
options ne2 io=0x300 irq=11

Questo dovrebbe bastare a rendere automatica la gestione dei due moduli nel momento in cui si utilizza il programma `ifconfig' per configurare le schede.

22.4.2 plip

Il modulo `plip' permette di gestire una o più porte parallele per una connessione punto-punto attraverso un cavo parallelo apposito. Generalmente è opportuno non indicare alcuna configurazione nel file `/etc/conf.modules': il modulo dovrebbe essere in grado di accedere a tutte le porte parallele disponibili.

22.4.3 Adattatori SCSI

Convenzionalmente, si tende ad assegnare l'alias `scsi_hostadapter' al modulo necessario per pilotare l'eventuale scheda SCSI presente nel proprio elaboratore.

alias scsi_hostadapter aic7xxx

L'esempio mostra una riga del file `/etc/conf.modules' in cui si dichiara l'alias in questione e lo si abbina al modulo `aic7xxx'. Il problema degli adattatori SCSI può essere più complesso se si intende utilizzare un sistema che si avvia a partire da un disco fisso SCSI, e contemporaneamente si vuole utilizzare un modulo per questo scopo. Il problema è già stato affrontato nella discussione sul disco RAM iniziale.

22.4.4 Porta parallela

Con i kernel 2.2.*, la gestione dei dispositivi che fanno uso della porta parallela è cambiata. Attualmente, si definisce prima l'uso della porta e quindi l'uso di altri moduli che ne fanno uso.

La gestione della porta parallela, a livello di modulo, è scissa in due parti: quella generica e quella specifica per il tipo di hardware.

I dispositivi o le interfacce di rete che fanno uso della porta parallela, possono indicare la porta, o le porte, a cui vogliono fare riferimento al caricamento del modulo relativo.

Esempi

Porte parallele per i386: indirizzi di I/O 0x3bc, 0x378 e 0x278; per quanto riguarda i livelli di IRQ, il primo non viene definito, il secondo è 7, l'ultimo deve essere determinato automaticamente.

Modulo `parport_pc'.

io=0x3bc,0x378,0x278 irq=none,7,auto

Due stampanti parallele che utilizzano rispettivamente la prima e la terza porta parallela.

Modulo `lp'.

lp parport=0,2

22.5 Riferimenti

---------------------------

Appunti Linux 2000.04.12 --- Copyright © 1997-2000 Daniele Giacomini --  daniele @ pluto.linux.it


[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]