LKN: Personalizzare un Kernel: differenze tra le versioni

revisionata
(rimosso tag <tt>)
(revisionata)
Riga 1: Riga 1:
{{Template:LKN}}
{{LKN}}


Uno dei punti più delicati e difficili nella creazione della propria versione del kernel Linux è quello di determinare esattamente quali driver e quali opzioni di configurazione sono richiesti per il corretto funzionamento dalla macchina su cui viene installato.
Uno dei punti più delicati e difficili nella compilazione della propria versione del kernel Linux è quello di determinare esattamente quali driver e quali opzioni di configurazione sono richiesti per il corretto funzionamento della macchina su cui sarà eseguito.
Questo capitolo guiderà il lettore attraverso questo processo di selezione e scelta dei driver corretti.
Questo capitolo guiderà il lettore attraverso questo processo di ricerca e selezione dei driver corretti.


==Usare un kernel di una distribuzione==
==Usare un kernel di una distribuzione==
Uno dei metodi più semplici, per determinare quali moduli siano necessari, è quello di partire dalla configurazione che viene installata dal pacchetto del kernel della distribuzione che si sta usando. È infatti molto più semplice determinare di quali driver si ha bisogno basandosi su quelli installati in un sistema in funzione, in cui i driver corretti sono già associati all'hardware in utilizzo.
Uno dei metodi più semplici, per determinare quali moduli siano necessari, è quello di partire dalla configurazione che viene installata dal pacchetto del kernel della distribuzione che si sta usando. È infatti molto più semplice determinare di quali driver si ha bisogno basandosi su quelli installati in un sistema in funzione, in cui i driver corretti sono già associati all'hardware in utilizzo.


Se invece si sta personalizzando un kernel per una macchina sulla quale non è installata una distribuzione Linux, allora conviene partire dalla versione LiveCD di una distribuzione. Questo consente all'utente di far partire Linux sulla macchina in oggetto e di determinare in maniera semplice le opzioni di configurazione del kernel e che consentono il funzionamento ottimale della macchina stessa.
Se invece si sta personalizzando un kernel per una macchina sulla quale non è installata una distribuzione Linux, allora conviene partire dalla versione LiveCD di una distribuzione. Questo consente all'utente di far partire Linux sulla macchina in oggetto e di determinare le opzioni di configurazione del kernel necessarie al suo corretto funzionamento su quell'hardware.


===Dove si trova la configurazione del kernel?===
===Dove si trova la configurazione del kernel?===
Quasi tutte le distribuzioni forniscono il file di configurazione nello stesso pacchetto del kernel. Si consiglia di leggere la documentazione relativa alla distribuzione stessa per sapere dove viene installato il file di configurazione. Solitamente si trova da qualche parte in una sotto-directory di <code>/usr/src/linux/</code>.
Quasi tutte le distribuzioni forniscono il file di configurazione nello stesso pacchetto del kernel. Si consiglia di leggere la documentazione relativa alla distribuzione stessa per sapere dove viene installato il file di configurazione. Solitamente si trova da qualche parte in una sotto-directory di <code>/usr/src/linux/</code>.


Riga 17: Riga 15:


Se avete difficoltà a trovare la configurazione del kernel, allora guardate nel kernel stesso. I kernel di molte distribuzioni sono compilati in modo da includere il file di configurazione dentro il filesystem <code>/proc</code>. Per verificare se questo è il vostro caso, digitate:
Se avete difficoltà a trovare la configurazione del kernel, allora guardate nel kernel stesso. I kernel di molte distribuzioni sono compilati in modo da includere il file di configurazione dentro il filesystem <code>/proc</code>. Per verificare se questo è il vostro caso, digitate:
<pre>
<pre>
$ ls /proc/config.gz
$ ls /proc/config.gz
/proc/config.gz
/proc/config.gz
</pre>
</pre>
Se il file ''/proc/config.gz'' è presente, allora copiatelo nella directory del sorgente kernel ed estraetelo:
Se il file ''/proc/config.gz'' è presente, allora copiatelo nella directory del sorgente kernel ed estraetelo:
<pre>
<pre>
$ cp /proc/config.gz -/linux/
$ cp /proc/config.gz -/linux/
Riga 31: Riga 26:
config.gz:      74.9% - - replaced with config
config.gz:      74.9% - - replaced with config
</pre>
</pre>
Copiate questo file di configurazione nella vostra directory del kernel e rinominatelo in ''.config''.
Copiate questo file di configurazione nella vostra directory del kernel e rinominatelo in ''.config''.
Ora potrete utilizzare questo file come base di partenza nella personalizzazione della configurazione del kernel così come descritto nel [[LKN:_Configurare_e_Compilare|Capitolo 4]].
Ora potrete utilizzare questo file come base di partenza nella personalizzazione della configurazione del kernel, così come descritto nel [[LKN:_Configurare_e_Compilare|Capitolo 4]].


Usando questo file di configurazione si dovrebbe ottenere sempre un file immagine del kernel (un ''kernel ricompilato'', NdT) funzionante sulla propria macchina.
Usando questo file di configurazione si dovrebbe ottenere sempre un file immagine del kernel (un ''kernel ricompilato'', NdT) funzionante sulla propria macchina.
Lo svantaggio di questa immagine è che verranno compilati quasi tutti i moduli e driver presenti nei sorgenti del kernel. Ciò non è quasi mai necessario per una singola macchina, quindi sarebbe meglio disabilitare tutti i driver e le opzioni non necessarie. Si raccomanda di disabilitare solo quelle opzioni che si è sicuri non serviranno, poiché ci sono parti del sistema che richiedono l'abilitazione di certe opzioni.
Lo svantaggio di questa immagine è che verranno compilati quasi tutti i moduli e driver presenti nei sorgenti del kernel. Ciò non è quasi mai necessario per una singola macchina, quindi sarebbe meglio disabilitare tutti i driver e le opzioni non necessarie. Si raccomanda di disabilitare solo quelle opzioni che si è sicuri non serviranno, poiché ci potrebbero essere parti del sistema che richiedono l'abilitazione di certe opzioni.


===Determinare quali moduli siano necessari===
===Determinare quali moduli sono necessari===
Usando il file di configurazione fornito dalla vostra distribuzione il tempo richiesto per la compilazione del kernel è molto lungo poiché tutti i possibili driver vengono abilitati. Si dovrebbe cercare di abilitare solo i driver per l'hardware presente nel sistema, così da ridurre i tempi di compilazione del kernel. Inoltre, compilando ''staticamente'' (invece che come moduli) alcuni o tutti i driver necessari, si riduce la memoria utilizzata ed in alcune architetture si velocizza il funzionamento del sistema. Per escludere i driver dal kernel è necessario però determinare quali moduli sono indispensabili per il funzionamento dell'hardware installato. Attraverso l'utilizzo di due esempi, cercheremo di spiegare come determinare quali driver siano indispensabili al controllo dell'hardware.
Usando il file di configurazione fornito dalla vostra distribuzione il tempo richiesto per la compilazione del kernel è molto lungo poiché tutti i possibili driver vengono abilitati. Si dovrebbe cercare di abilitare solo i driver per l'hardware presente nel sistema, così da ridurre i tempi di compilazione del kernel e permettere la compilazione di tutti o parte dei driver nel kernel stesso (compilando ''staticamente'' invece che come moduli NdT), riducendo un po' la memoria utilizzata e, in alcune architetture, creando un kernel che sarà eseguito più velocemente. Per escludere i driver dal kernel è necessario determinare quali moduli sono indispensabili per il funzionamento dell'hardware installato. Attraverso l'utilizzo di due esempi, cercheremo di spiegare come determinare quali driver siano indispensabili al controllo dell'hardware.


Le informazioni che mettono in relazione i dispositivi ai driver presenti nel kernel sono conservate in varie parti del sistema. Uno dei posti più importanti dove sono salvate queste informazioni è il filesystem virtuale ''sysfs''. All'avvio di Linux, ''sysfs'', dovrebbe essere montato dagli script di inizializzazione della vostra distribuzione nella directory ''/sys''. ''sysfs'' consente di dare un'occhiata a come le varie parti del kernel sono legate l'una a l'altra, questo lo si deduce grazie ai vari collegamenti simbolici (''symlink'' NdT) che puntano all'interno dell'intero filesystem.
Le informazioni che mettono in relazione i dispositivi ai driver presenti nel kernel sono conservate in varie parti del sistema. Uno dei posti più importanti dove sono salvate queste informazioni è il filesystem virtuale ''sysfs''. All'avvio di Linux ''sysfs'' dovrebbe essere montato dagli script di inizializzazione della vostra distribuzione nella directory ''/sys''. ''sysfs'' consente di dare un'occhiata a come le varie parti del kernel sono legate l'una a l'altra, questo lo si deduce grazie ai vari collegamenti simbolici (''symlink'' NdT) che puntano all'interno dell'intero filesystem.


In tutti gli esempi di seguito, saranno riportati i veri percorsi (''path'' NdT) di ''sysfs'' corrispondenti ad hardware specifico. La vostra macchina sarà certamente diversa, ma la posizione  relativa delle informazioni sarà la stessa. Non ci si deve allarmare se i nomi di file nel ''sysfs'' non sono i medesimi, ciò è normale e prevedibile.
In tutti gli esempi di seguito, saranno riportati i veri percorsi (''path'' NdT) di ''sysfs'' corrispondenti ad hardware specifico. La vostra macchina sarà certamente diversa, ma la posizione  relativa delle informazioni sarà la stessa. Non ci si deve allarmare se i nomi di file nel ''sysfs'' non sono i medesimi, ciò è normale e prevedibile.


Inoltre, la struttura interna del file di sistema ''sysfs'' subisce modifiche, a causa sia della riorganizzazione dei driver sia del fatto che gli sviluppatori del kernel trovano nuovi modi per meglio presentare in ''user space'' le strutture interne del kernel. A causa di questo, col tempo, alcuni dei ''symlink'', precedentemente menzionati in questo capitolo, possono non essere presenti. Tuttavia, le informazioni sono ancora tutte presenti, al massimo sono state un po' spostate.
Inoltre, la struttura interna del file di sistema ''sysfs'' subisce modifiche, a causa sia della riorganizzazione dei driver sia dei ripensamenti degli sviluppatori del kernel su come presentare al meglio in ''user space'' le strutture interne del kernel. A causa di questo, col tempo, alcuni dei ''symlink'' precedentemente menzionati in questo capitolo possono non essere presenti. Comunque le informazioni saranno ancora tutte , solo spostate un po'.


====Esempio: Come determinare il driver di rete====
====Esempio: Come determinare il driver di rete====
Uno dei dispositivi (''device'' NdT) più comuni ed importanti in un sistema è la scheda di rete. È essenziale capire quale driver la controlla ed attivarlo nella configurazione in maniera da consentire un corretto funzionamento delle connessioni di rete.


Uno degli elementi più comuni ed importanti in un sistema è la scheda di rete. È essenziale capire quale driver la controlla ed attivarlo nella configurazione in maniera da consentire un corretto funzionamento delle connessioni di rete.
In primo luogo, partendo dal nome dell'interfaccia di rete si deve risalire al device PCI che la sta controllando. I nomi delle interfacce di rete si ottengono come segue:
<pre>
$ ls /sys/class/net/
eth0  eth1  eth2  lo
</pre>
La directory ''lo'' rappresenta solo il dispositivo di rete loopback, che non è connesso e nessun reale dispositivo di rete. Invece si deve prestare attenzione alle directory ''eth0'', ''eth1'' e ''eth2'', dato che si riferiscono a dispositivi realmente esistenti.


Primo: partendo dalle connessioni di rete si risale al device PCI
Per ottenere maggiori informazioni su questi dispositivi, si utilizza il comando ''ifconfig'':
<pre>$ ls /sys/class/net/
<pre>
eth0  eth1  eth2  lo</pre>
$ /sbin/ifconfig -a
 
La directory ''lo'' rappresenta il dispositivo di rete loopback, ed non è dipendente da nessun dispositivo di rete realmente installato. Invece si dovrebbe riservare particolare attenzione alle directory ''eth0'', ''eth1'' e ''eth2'', dato che si riferiscono a dispositivi realmente esistenti
 
Per determinare di quali dispositivi ci si deve occupare, si utilizza il comando ''ifconfig'':
 
<pre>$ /sbin/ifconfig -a
eth0 Link  encap:Ethernet  HWaddr 00:12:3F:65:7D:C2
eth0 Link  encap:Ethernet  HWaddr 00:12:3F:65:7D:C2
inet  addr:192.168.0.13  Bcast:192.168.0.255  Mask:255.255.255.0
inet  addr:192.168.0.13  Bcast:192.168.0.255  Mask:255.255.255.0
Riga 71: Riga 65:
BROADCAST MULTICAST  MTU:1500  Metric:1
BROADCAST MULTICAST  MTU:1500  Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Riga 86: Riga 80:
TX packets:60 errors:0 dropped:0 overruns:0 carrier:0
TX packets:60 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
collisions:0 txqueuelen:1000
RX bytes:13409 (13.0 Kb) TX bytes:13409 (13.0 Kb)</pre>
RX bytes:13409 (13.0 Kb) TX bytes:13409 (13.0 Kb)
</pre>
Da questo listato si può riconoscere nel dispositivo di rete <code>eth0</code> quello attivo e funzionante, come si può vedere dalle righe:
<pre>
eth0 Link  encap:Ethernet  HWaddr 00:12:3F:65:7D:C2
inet  addr:192.168.0.13  Bcast:192.168.0.255  Mask:255.255.255.0
</pre>
Questo risultato mostra che tale dispositivo è di tipo Ethernet e gli è stato assegnato un indirizzo IP valido (<code>inet</code>).


Da questo listato si può riconoscere nel dispositivo di rete <code>eth0</code>, quello attivo e funzionante, infatti nelle righe;
Ora, dopo che abbiamo individuato il dispositivo <code>eth0</code> e ci siamo accertati di volerlo abilitare nel nostro nuovo kernel, dobbiamo individuare quale driver lo controlla. Ciò si realizza con una semplice procedura, che è quella di seguire i diversi link nel filesystem sysfs, eseguibile con un comando di una sola riga:
 
<pre>
<pre>eth0 Link  encap:Ethernet  HWaddr 00:12:3F:65:7D:C2
$ basename `readlink /sys/class/net/eth0/device/driver/module`
inet  addr:192.168.0.13  Bcast:192.168.0.255  Mask:255.255.255.0</pre>
e1000
 
</pre>
Questo risultato dimostra che il dispositivo Ethernet si vede assegnato un indirizzo IP valido (<code>inet</code>).
 
Ora, dopo che abbiamo individuato il dispositivo <code>eth0</code> e ci siamo accertati di volerlo abilitare nel nostro nuovo kernel, dobbiamo individuare quale driver lo controlla. Ciò si realizza con una semplice procedura, che è quella si seguire i link nel filesystem sysfs, basta digitare un comando di una sola riga:
 
<pre>$ basename `readlink /sys/class/net/eth0/device/driver/module`
e1000</pre>
 
Il risultato mostra che il modulo <code>e1000</code> controlla il dispositivo di rete <code>eth0</code>. Il comando ''basename'' racchiude in un'unica linea di comando i seguenti passaggi:


: 1. Individua il symlink ''/sys/class/net/eth0/device'' contenuto all'interno della directory ''/sys/device/'', la quale contiene le informazioni relative al dispositivo che controlla ''eth0''. Fate attenzione al fatto che nelle nuove versioni del kernel la directory ''/sys/class/net/eth0'' potrebbe essere un symlink.  
Il risultato mostra che il modulo chiamato <code>e1000</code> controlla il dispositivo di rete <code>eth0</code>. Il comando ''basename'' appena mostrato racchiude in un'unica riga i seguenti passaggi:
 
# Segue il percorso a cui punta il symlink ''/sys/class/net/eth0/device'', contenuto all'interno della directory ''/sys/device/'', che contiene le informazioni relative al dispositivo che controlla ''eth0''. Notare che nelle versioni più recenti del kernel la directory ''/sys/class/net/eth0'' potrebbe essere anch'essa un symlink.  
: 2. All'interno della directory che descrive il dispositivo in sysfs, c'è un symlink che punta al driver relativo a questo dispositivo. Questo symlink è nominato ''driver'', pertanto si segue questo collegamento.
# All'interno della directory che descrive il dispositivo in ''sysfs'', c'è un symlink che punta al driver relativo a questo dispositivo. Questo symlink è nominato ''driver'', pertanto si segue questo collegamento.
 
# All'interno della directory che descrive il driver in ''sysfs'', c'è un symlink che punta al modulo che si trova all'interno del driver in oggetto. Questo symlink è chiamato <code>module</code>. Noi cerchiamo il file a cui punta questo symlink, per ottenerlo ci serviamo del comando ''readlink'', il quale produce un risultato simile a questo: <pre>$ readlink /sys/class/net/eth0/device/driver/module</pre><pre>../../../../module/e1000</pre>
: 3. All'interno della directory che descrive il driver in sysfs, c'è un symlink che punta al modulo che si trova all'interno del driver in oggetto. Questo symlink è chiamato <code>module</code>. Noi cerchiamo l'oggetto a cui punta questo symlink, per ottenerlo ci serviamo del comando ''readlink'', il quale produce un risultato simile a questo:
# Dato che a noi interessa solo il nome del modulo, vogliamo scartare il resto del risultato ottenuto con il comando ''readlink'', tenendo solo la parte più a destra del risultato. Questo è appunto ciò che il comando ''basename'' realizza. Applicandolo direttamente all'intero percorso, ritorna quanto segue:<pre>$ basename ../../../../module/e1000</pre><pre>e1000</pre>
:<pre>$ readlink /sys/class/net/eth0/device/driver/module </pre>
Così abbiamo inserito il lungo percorso ottenuto seguendo il symlink, ottenuto grazie a ''readlink'', quale parametro del programma ''basename'', permettendo così l'intero processo di essere realizzato in una sola riga.
:<pre> ../../../../module/e1000</pre>
 
: 4. Dato che a noi interessa solo il nome del modulo e ci disinteressiamo del resto del risultato ottenuto con il comando ''readlink'', tenendo solo la parte più a destra del risultato. Questo è appunto ciò che il comando ''basename'' realizza. Applicandolo direttamente all'intero percorso, questo comando ci ritorna quanto segue:
: <pre>$ basename ../../../../module/e1000</pre>
: <pre>e1000</pre>
 
Così abbiamo inserito il lungo risultato del symlink, ottenuto da ''readlink'', quale parametro nel programma ''basemane'', permettendo così l'intero processo di essere realizzato in una sola riga.
 
Ora che abbiamo identificato il nome del modulo, si dovrebbe trovare l'opzione della configurazione del kernel che lo controlla. Si può cercare nei vari menu di configurazione dei dispositivi di rete oppure cercare nel codice sorgente del kernel stesso per essere sicuri di avere l'opzione giusta.


Ora che abbiamo il nome del modulo, si deve trovare l'opzione di configurazione del kernel che lo controlla. Si può cercare nei vari menu di configurazione dei dispositivi di rete oppure cercare nel codice sorgente del kernel stesso per essere sicuri di avere l'opzione giusta:
<pre>
<pre>
$ cd ~/linux/linux-2.6.17.8
$ cd ~/linux/linux-2.6.17.8
Riga 126: Riga 111:
</pre>
</pre>


Si precisa che "e1000'', usato in questo esempio, deve essere sostituito con il nome del modulo che state analizzando.
Si ricordi di sostituire il nome '''e1000''', usato in questo esempio, con quello del modulo che avete intenzione di trovare.


La cosa che ci interessa nel risultato del precedente comando ''find'' sono le righe dove compaia il termine <code>'''CONFIG_'''</code>. Questa è l'opzione di configurazione che il kernel deve aver attivato per poter compilare il modulo. Nell'esempio precedente l'opzione di configurazione che c'interessa è pertanto <code>CONFIG_E1000</code>.
La cosa importante da cercare nel risultato del precedente comando ''find'' sono le righe dove compare il termine <code>'''CONFIG_'''</code>. Questa è l'opzione di configurazione che il kernel deve aver attivato per poter compilare il modulo. Nell'esempio precedente l'opzione di configurazione che ci interessa è pertanto <code>CONFIG_E1000</code>.
 
Adesso si dispone dell'informazione necessaria per poter configurare il kernel. Si esegue lo strumento menu di configurazione:


Adesso si dispone dell'informazione necessaria per poter configurare il kernel. Si esegue lo strumento di configurazione a menù:
<pre>$ make menuconfig</pre>
<pre>$ make menuconfig</pre>


Dopodiché si prema il tasto / (slash) (che ha il compito di far partire una ricerca), e si digita l'opzione di configurazione, senza la parte di testo <code>CONFIG_</code>. Questo processo è mostrato nella [[:Immagine:Config_search.png|figura 7-1]].
Dopodiché si prema il tasto '''<code>/</code>''' (slash) (che ha il compito di far partire una ricerca), e si digiti l'opzione di configurazione, senza la parte di testo <code>CONFIG_</code>. Questo processo è mostrato nella [[:Immagine:Config_search.png|figura 7-1]].


[[Immagine:Config_search.png|center|frame|''Figura 7-1. Ricerca in menuconfig.'']]
[[Immagine:Config_search.png|center|frame|''Figura 7-1. Ricerca in menuconfig.'']]


Il sistema di configurazione del kernel vi dirà ora esattamente dove selezionare l'opzione per abilitare questo modulo. Vedi [[:Immagine:Config_search_found.png|figura 7-2]].
Il sistema di configurazione del kernel dirà ora esattamente dove selezionare l'opzione per abilitare questo modulo. Si veda la [[:Immagine:Config_search_found.png|figura 7-2]].


[[Immagine:Config_search_found.png|center|frame|''Figura 7-2. Risultato della ricerca in menuconfig.'']]
[[Immagine:Config_search_found.png|center|frame|''Figura 7-2. Risultato della ricerca in menuconfig.'']]


Il primo elemento nella schermata mostra l'opzione che stavate cercando. Le informazioni mostrate dalla schermata vi dicono che, per attivare il modulo <code>E1000</code> nel kernel, la seguente opzione di configurazione deve essere abilitata:
Il primo elemento nella schermata mostra l'opzione che stavate cercando. Le informazioni mostrate dalla schermata vi dicono che, per attivare il modulo <code>E1000</code> nel kernel, la seguente opzione di configurazione deve essere abilitata:
 
<pre>
  Device Drivers
Device Drivers
      Network device support
    Network device support
      [*] Network device support
    [*] Network device support
          Ethernet (1000 Mbit)
        Ethernet (1000 Mbit)
      [*] Intel(R) PRO/1000 Gigabit Ethernet support
    [*] Intel(R) PRO/1000 Gigabit Ethernet support
 
</pre>
Questo modo di procedere funziona per ogni tipo di dispositivo attivo nel kernel.
Questo modo di procedere funziona per ogni tipo di dispositivo attivo nel kernel.


====Esempio: Un dispositivo USB====
====Esempio: Un dispositivo USB====
 
Come secondo esempio, esaminiamo ora un convertitore USB-seriale che è presente nel sistema. Attualmente il convertitore è collegato alla porta ''/dev/ttyUSB0'', pertanto si deve prendere in esame la sezione tty del ''sysfs''.
Come secondo esempio, esaminiamo ora un convertitore USB-seriale che è presente nel nostro sistema preso ad esempio. Attualmente il convertitore è collegato alla porta ''/dev/ttyUSB0'', pertanto si deve prendere in esame la sezione tty del ''sysfs''.
<pre>
<pre>$ ls /sys/class/tty/ | grep USB
$ ls /sys/class/tty/ | grep USB
ttyUSB0</pre>
ttyUSB0
Potete ora eseguire una ricerca di questo dispositivo nel ''sysfs'' allo scopo di trovare il modulo che lo gestisce, utilizzando la stessa procedura mostrata nella sezione precedente:
</pre>
 
Si può ora eseguire una ricerca di questo dispositivo nel ''sysfs'' allo scopo di trovare il modulo che lo gestisce, utilizzando la stessa procedura mostrata nella sezione precedente:
<pre>$ basename `readlink /sys/class/tty/ttyUSB0/device/driver/module`
<pre>
pl2303</pre>
$ basename `readlink /sys/class/tty/ttyUSB0/device/driver/module`
pl2303
</pre>
Dopodiché, per poter individuare l'opzione di configurazione che si deve abilitare, si cerca nell'albero del codice sorgente del kernel:
Dopodiché, per poter individuare l'opzione di configurazione che si deve abilitare, si cerca nell'albero del codice sorgente del kernel:
<pre>$ cd ~/linux/linux-2.6.17.8
<pre>
$ cd ~/linux/linux-2.6.17.8
$ find -type f -name Makefile | xargs grep pl2303
$ find -type f -name Makefile | xargs grep pl2303
./drivers/usb/serial/Makefile:obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o</pre>
./drivers/usb/serial/Makefile:obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
 
</pre>
Si utilizzi lo strumento di configurazione del kernel, come indicato in [[:Immagine:Config_search_pl2303.png|figura 7-3]], per trovare l'opzione adeguata da abilitare relativa al settaggio dell'opzione CONFIG_USB_SERIAL_PL2303.
Si utilizzi lo strumento di configurazione del kernel, come indicato in [[:Immagine:Config_search_pl2303.png|figura 7-3]], per trovare l'opzione adeguata da abilitare, relativa al settaggio dell'opzione <code>CONFIG_USB_SERIAL_PL2303</code>.


[[Immagine:Config_search_pl2303.png|center|frame|''Figura 7-3. Ricerca di USB_SERIAL_PL2303''.]]
[[Immagine:Config_search_pl2303.png|center|frame|''Figura 7-3. Ricerca di USB_SERIAL_PL2303''.]]
Riga 174: Riga 161:
[[Immagine:Config_search_pl2303_found.png|center|frame|''Figura 7-4. Risultato della ricerca di USB_SERIAL_PL2303'']]
[[Immagine:Config_search_pl2303_found.png|center|frame|''Figura 7-4. Risultato della ricerca di USB_SERIAL_PL2303'']]


Ciò mostra esattamente dove trovare l'opzione <code>USB Profilic 2303 Single Port Serial Driver</code> che è necessaria alla corretta gestione di questo dispositivo.
Ciò mostra esattamente dove trovare l'opzione <code>USB Profilic 2303 Single Port Serial Driver</code>, che è necessaria alla corretta gestione di questo dispositivo.
 
====Riassunto: Alla scoperta del dispositivo====


====Sommario della scoperta del dispositivo====
Riassumendo, ecco i vari passaggi che servono per identificare il driver funzionante di un dispositivo ad esso collegato:
Riassumendo, ecco i vari passaggi che servono per identificare il driver funzionante di un dispositivo ad esso collegato:
: 1. Trovate la corretta classe di dispositivi in ''sysfs'' relativa al dispositivo che ci interessa. I dispositivi di rete sono elencati in ''/sys/class/net'', mentre i dispositivi tty sono elencati in ''/sys/class/tty''. Gli altri vari dispositivi si trovano in altre sotto-directory di ''/sys/class'', a seconda del tipo.
# Trovare la corretta classe di dispositivi in ''sysfs'' relativa al dispositivo che ci interessa. I dispositivi di rete sono elencati in ''/sys/class/net'', mentre i dispositivi tty sono elencati in ''/sys/class/tty''. Gli altri vari dispositivi si trovano in altre sotto-directory di ''/sys/class'', a seconda del tipo.
: 2. Ricercate nell'albero di ''sysfs'' il nome del modulo che controlla il dispositivo in oggetto. Lo si trova in ''/sys/class/class_name/device_name/device/driver/module'', la ricerca è agevolata se si utilizzano i comandi ''readlink'' e ''basename''.
# Seguire i link simboilci nell'albero di ''sysfs'' per trovare il nome del modulo che controlla il dispositivo in oggetto. Lo si trova seguendo il symlink ''/sys/class/class_name/device_name/device/driver/module'', e può essere visualizzato combinando i comandi ''readlink'' e ''basename'':<pre>$ basename `readlink /sys/class/class_name/device_name/device/driver/module`</pre>
:<pre>$ basename `readlink /sys/class/class_name/device_name/device/driver/module`</pre>
# Ricercare nei file Makefile con ''find'' e ''grep'' le opzioni <code>CONFIG_</code> usate per compilare il modulo: <pre>$ find -type f -name Makefile | xargs grep ''module_name''</pre>
: 3. Ricercate nei file Makefile con ''find'' e ''grep'' le opzioni <code>CONFIG_</code> che abilitano il modulo
# Ricercare l'opzione trovata nel sistema di configurazione del kernel, dopodiché andare nella posizione del menù che specifica di attivare quel driver per compilarlo.
:<pre>$ find -type f -name Makefile | xargs grep ''module_name''</pre>
: 4. Ricercate l'opzione trovata nel sistema di configurazione del kernel, dopodiché andate dove indicato dal menu per attivare il driver in oggetto.


====Lasciamo che il kernel ci dica ciò di cui abbiamo bisogno====
====Lasciamo che il kernel ci dica ciò di cui abbiamo bisogno====
Dopo esserci infilati nel ''sysfs'' e aver seguito i sui symlinks per ricercare passo passo i nomi dei moduli, presentiamo un semplice script che farà per noi tutto il lavoro in un modo leggermente diverso:
Dopo esserci infilati nel ''sysfs'' e aver seguito i sui symlinks per ricercare passo passo i nomi dei moduli, presentiamo un semplice script che farà per noi tutto il lavoro in un modo leggermente diverso:
<pre>
<pre>
#!/bin/bash
#!/bin/bash
Riga 205: Riga 188:
Lo script prevede l'arresto del programma ''modprobe'' prima di caricare il modulo, e visualizza a schermo solo le azioni che eseguirebbe. Questo ci d&agrave; una lista di tutti i moduli che sono necessari al controllo di tutti i dispositivi del sistema. Eseguendo una piccola pulizia della lista, ordinandola e selezionando i campi adeguati,  
Lo script prevede l'arresto del programma ''modprobe'' prima di caricare il modulo, e visualizza a schermo solo le azioni che eseguirebbe. Questo ci d&agrave; una lista di tutti i moduli che sono necessari al controllo di tutti i dispositivi del sistema. Eseguendo una piccola pulizia della lista, ordinandola e selezionando i campi adeguati,  
otteniamo il seguente risultato:
otteniamo il seguente risultato:
<pre>
<pre>
$ find_all_modules.sh
$ find_all_modules.sh
Riga 236: Riga 218:


Lo script mostrerà probabilmente alcuni messaggi di errore che possono essere del tipo:
Lo script mostrerà probabilmente alcuni messaggi di errore che possono essere del tipo:
 
<pre>
<pre>FATAL: Module pci:v00008086d00002592sv000010CFsd000012E0bc03sc00i00 not found.
FATAL: Module pci:v00008086d00002592sv000010CFsd000012E0bc03sc00i00 not found.
FATAL: Module serio:ty01pr00id00ex00 not found.</pre>
FATAL: Module serio:ty01pr00id00ex00 not found.
</pre>


Questo ci dice che non si trova un modulo che gestisce quel dispositivo. Questo non deve comunque interessare più di tanto, poiché alcuni dispositivi non hanno driver nel kernel che lavorino per loro.
Questo ci dice che non si trova un modulo che gestisce quel dispositivo. Questo non deve comunque interessare più di tanto, poiché alcuni dispositivi non hanno driver nel kernel che lavorino per loro.


==Determinare il modulo corretto partendo da zero==
==Determinare il modulo corretto partendo da zero==
Talvolta non c'è la possibilità di avere un kernel funzionante su una macchina in modo da determinare quali moduli del kernel siano necessari per gestire l'hardware. Oppure si è aggiunto del nuovo hardware al sistema e bisogna trovare le opzioni della configurazione necessarie a farlo funzionare correttamente. Questa sezione illustrerà come determinare le opzioni di configurazione necessarie ad far funzionare l'hardware.
Talvolta non c'è la possibilità di avere un kernel funzionante su una macchina in modo da determinare quali moduli del kernel siano necessari per gestire l'hardware. Oppure si è aggiunto del nuovo hardware al sistema e bisogna trovare le opzioni della configurazione necessarie a farlo funzionare correttamente. Questa sezione illustrerà come determinare le opzioni di configurazione necessarie a far funzionare l'hardware.


Il modo più semplice per capire quale driver controlla un nuovo dispositivo è quello di compilare come moduli tutti i driver di quel tipo disponibili nei sorgenti del kernel, e lasciare che il processo di avvio tramite ''udev'' associ il driver al dispositivo. Una volta fatto ciò, si dovrebbe essere in grado di risalire al driver necessario seguendo i passi descritti precedentemente, ed infine ricompilare il kernel abilitando il solo driver necessario.
Il modo più semplice per capire quale driver controlla un nuovo dispositivo è quello di compilare come moduli tutti i driver di quel tipo disponibili nei sorgenti del kernel, e lasciare che il processo di avvio tramite ''udev'' associ il driver al dispositivo. Una volta fatto ciò, si dovrebbe essere in grado di risalire al driver necessario seguendo i passi descritti precedentemente, e infine ricompilare il kernel abilitando il solo driver necessario.


Se invece non si vogliono compilare tutti i driver, o questo meccanismo non funziona per qualche motivo, sarà necessario un pò più di lavoro per individuare il driver necessario. I passi successivi sono complessi e richiedono talvolta di dover cercare nei sorgenti del kernel. Non abbiate timore di ciò, sarà solo di aiuto a comprendere meglio l'hardware ed i sorgenti del kernel.
Se invece non si vogliono compilare tutti i driver, o questo meccanismo non funziona per qualche motivo, sarà necessario un pò più di lavoro per individuare il driver necessario. I passi successivi sono complessi e richiedono talvolta di dover cercare nei sorgenti del kernel. Non abbiate timore di ciò, sarà solo di aiuto a comprendere meglio l'hardware ed i sorgenti del kernel.


I passi necessari per trovare il driver corrispondente di un dispositivo cambiano a seconda del tipo di dispositivo in questione. In questo capitolo discuteremo le due tipologie di dispositivi più comuni: PCI e USB. I metodi descritti qui saranno validi anche per altri tipi di dispositivi.
I passi necessari per trovare il driver corrispondente di un dispositivo cambiano a seconda del tipo di dispositivo in questione. In questo capitolo discuteremo le due tipologie di dispositivi più comuni: PCI e USB; ma i metodi qui descritti saranno validi anche per altri tipi di dispositivi.
 
&Egrave; inoltre molto importante per il kernel di essere in grado di trovare tutti i filesystem presenti nel sistema, ed in particolare il filesystem di root. Approfondiremop questo aspetto successivamente in [[LKN: Personalizzare un Kernel#Root filesystem|"Root filesystem"]].


&Egrave; inoltre molto importante per il kernel di essere in grado di trovare tutti i filesystem presenti nel sistema, di cui il più importante è quello radice (''root'' NdT). Approfondiremop questo aspetto successivamente in [[LKN: Personalizzare un Kernel#Root filesystem|"Root filesystem"]].


===Dispositivi PCI===
===Dispositivi PCI===
Riga 259: Riga 241:
Per questo esempio useremo un scheda di rete PCI che supporremo non funzionante con l'attuare versione del kernele in esecuzione. Questo esempio sarà diverso dalla vostra situazione, con differenti device PCI e valori ID del bus, ma i passi salienti dovrebbero essere rilevanti per ogni tipo di dispositivo PCI per il quale vogliate trovare un driver funzionante.
Per questo esempio useremo un scheda di rete PCI che supporremo non funzionante con l'attuare versione del kernele in esecuzione. Questo esempio sarà diverso dalla vostra situazione, con differenti device PCI e valori ID del bus, ma i passi salienti dovrebbero essere rilevanti per ogni tipo di dispositivo PCI per il quale vogliate trovare un driver funzionante.


In primo luogo troviamo nel sistema il dispositivo PCI che non stà funzionando. Per ottenere una lista di tutti i dispositivi PCI usiamo il programma <code>lspci</code>. Poiché a noi interessano solo dispositivi PCI ethernet restringeremo la nostra ricerca filtrado tra i risultati solo quelli che conterranno la parola ''ethernet'' (case-insensitive):
In primo luogo troviamo nel sistema il dispositivo PCI che non sta funzionando. Per ottenere una lista di tutti i dispositivi PCI usiamo il programma <code>lspci</code>. Poiché a noi interessano solo dispositivi PCI ethernet restringeremo la nostra ricerca filtrado tra i risultati solo quelli che conterranno la parola ''ethernet'' (ignorando se i caratteri sono minuscoli o maiuscoli):
 
<pre>
<pre>
$ /usr/sbin/lspci | grep -i ethernet
$ /usr/sbin/lspci | grep -i ethernet
Riga 267: Riga 248:
</pre>
</pre>


Questo è il dispositivo che vorremmo fare funzionare.
Questo è il dispositivo che vorremmo fare funzionare.<sup>*</sup>


{{Box|Nota:|Potreste anche provare a cercare in tutta la configurazione del kernel un dispositivo che corrisponde alla stringa mostrata sopra (un dispositivo della Realtek Semiconductors con nome prodotto RTL-8139/8139C/8139C+), ma questo non funziona sempre. Per questo motivo useremo la via lunga in questo capitolo.}}
<small>Nota ('''<sup>*</sup>'''): potreste anche provare a cercare in tutta la configurazione del kernel un dispositivo che corrisponde alla stringa mostrata sopra (un dispositivo della Realtek Semiconductors con nome prodotto RTL-8139/8139C/8139C+), ma questo non funziona sempre. Per questo motivo useremo la via lunga in questo capitolo.</small>


::[[Immagine:Warning_65x68.jpg|left]] Quasi tutte le distribuzioni mettono il programma <code>lspci</code> in <code>/usr/sbin/</code>, ma alcune lo mettono in altri percorsi. Per trovare in quale posizione è stato messo digitare:
::[[Immagine:Warning_65x68.jpg|left]] Quasi tutte le distribuzioni mettono il programma <code>lspci</code> in <code>/usr/sbin/</code>, ma alcune lo mettono in altri percorsi. Per trovare in quale posizione è stato messo digitare:
Riga 276: Riga 257:
::<code>/usr/sbin/lspci</code>
::<code>/usr/sbin/lspci</code>


Se state usando una distribuzione che mette ''lspci'' in una altra posizione usate il percorso corretto per il vostro caso negli esempi seguenti.
Se state usando una distribuzione che mette ''lspci'' in un'altra posizione, usate il percorso corretto per la vostra installazione ogni volta che verrà usato ''lspci''.


Le primi bit d'informazione che l'output di ''lspci'' ci mostra sono l'ID del bus PCI per questo dispositivo, <code>06:04.0</code>. Questo è il valore che useremo quando guarderemo nel ''sysfs'' per trovare più informazioni riguardo questo dispositivo.
I primi pochi spezzoni dell'output di ''lspci'' mostrano l'ID del bus PCI per questo dispositivo, <code>06:04.0</code>. Questo è il valore che useremo quando cercheremo in ''sysfs'' per trovare più informazioni riguardo questo dispositivo.


Andiamo in ''sysfs'' dove tutti i dispositivi PCI sono elencati, e guardiamo i loro nomi:
Andiamo in ''sysfs'' dove tutti i dispositivi PCI sono elencati, e guardiamo i loro nomi:
<pre>
<pre>
$ cd /sys/bus/pci/devices/
$ cd /sys/bus/pci/devices/
Riga 291: Riga 271:
</pre>
</pre>


Il kernel numera i dispositivi PCI con un <code>0000:</code> iniziale che non viene mostrato nell'output di ''lspci''. Dunque, aggiungiamo un <code>0000:</code> al numero datoci da ''lspci'' e entriamo in quella directory:
Il kernel numera i dispositivi PCI con un <code>0000:</code> iniziale che non viene mostrato nell'output di ''lspci''.<sup>+</sup> Dunque, aggiungiamo un <code>0000:</code> al numero datoci da ''lspci'' e entriamo in quella directory:
<pre>
$ cd 0000:06:04.0
</pre>


  $ cd 0000:06:04.0
<small>Nota ('''<sup>+</sup>'''): alcuni processori 64-bit mostreranno il "leading bus number" per i dispositivi PCI nell'output di lspci, ma per la maggiorparte delle comuni macchine Linux, non verrà mostrato di default.</small>


In questa directory vogliamo conoscere il valori dei file ''vendor'' e ''device''.
In questa directory vogliamo conoscere il valori dei file ''vendor'' e ''device''.
<pre>
<pre>
$ cat vendor
$ cat vendor
0x10ec
0x10ec
$ cat device
$ cat device
0x8139
0x8139
Riga 305: Riga 288:


Questi sono il ''vendor ID'' ed il ''device ID'' per questo dispositivo PCI. Il kernel usa questi valori per associare correttamente un driver ad un dispositivo. I driver PCI dicono al kernel quale vendor e device ID supporteranno così che il kernel sappia come collegare il driver al dispositivo corretto. Scriveteli da qualche parte, dato che ci riferiremo a loro più tardi.
Questi sono il ''vendor ID'' ed il ''device ID'' per questo dispositivo PCI. Il kernel usa questi valori per associare correttamente un driver ad un dispositivo. I driver PCI dicono al kernel quale vendor e device ID supporteranno così che il kernel sappia come collegare il driver al dispositivo corretto. Scriveteli da qualche parte, dato che ci riferiremo a loro più tardi.
Ora che sappiamo il vendor e il product ID per questo dipositivo PCI, abbiamo bisogno di trovare i driver del kernel corretto che dica che supporta questo dispositivo. Tornate indietro alla directory di source del kernel:


      <B>$ cd ~/linux/linux-2.6.17.8/</B>
Ora che sappiamo il ''vendor ID'' e il ''device ID'' per questo dipositivo PCI, abbiamo bisogno di trovare i driver del kernel corretto che riporta di supportare questo dispositivo. Tornate indietro alla directory di source del kernel:
<pre>
$ cd ~/linux/linux-2.6.17.8/
</pre>
Il posto più comune per gli ID di tipo PCI nell'albero sorgente del kernel è ''include/linux/pci_ids.h''. Cercate in quel file il vostro ''vendor id'':
<pre>
$ grep -i 0x10ec include/linux/pci_ids.h
#define PCI_VENDOR_ID_REALTEK                  0x10ec
</pre>
Il valore qui definito, <code>PCI_VENDOR_ID_REALTEK</code>, è ciò che probabilmente sarà usato in qualsiasi kernel driver che riporta di supportare i dispositivi di quel produttore.


Il posto più comune per gli ID PCI nell'albero sorgente del kernel è include/linux/pci_ids.h. Cercate in quel file il vostro product number vendor:
Per essere sicuri, si cerchi il ''device ID'' anche in questo file , dato che è a volte descritto là:
<pre>
$ grep -i 0x8139 include/linux/pci_ids.h
#define PCI_DEVICE_ID_REALTEK_8139        0x8139
</pre>
Questa definizione sarà utile più avanti.


      <B>$ grep -i 0x10ec include/linux/pci_ids.h</B>
Ora si cerchi nei file sorgenti dei driver relativi a questo produttore:
      #define PCI_VENDOR_ID_REALTEK                  0x10ec
<pre>
$ grep -Rl PCI_VENDOR_ID_REALTEK *
include/linux/pci_ids.h
drivers/net/r8169.c
drivers/net/8139too.c
drivers/net/8139cp.c
</pre>


* Alcuni processori 64-bit mostreranno il "leading bus number" per i dispositivi PCI nell'output di lspci, ma per la maggiorparte delle comuni macchine Linux, non verrà mostrato di default.
Non serve guardare nel primo file riportato qui, ''pci_ids.h'', dato che è dove è stata trovata la definizione originale. Ma i file ''r8139.c'', ''8139too.c'', e ''8169cp.c'' nella sottodirectory ''drivers/net/'' dovrebbero essere esaminati più da vicino.


Il valore qui definito, PCI_VENDOR_ID_REALTEK è ciò che probabilmente sarà usato in qualsiasi kernel driver che ha la pretesa di supportare i dispositivi di quel produttore.
Si apra uno di questi file in un editor, cercando <code>PCI_VENDOR_ID_REALTEK</code>. Nel file ''drivers/net/r8169.c'', si vede nella seguente sezione di codice:
Per essere sicuri, cercate il nostro device ID anche in questo file , dato che è a volte descritto la:
<pre>
static struct pci_device_id rtl8169_pci_tbl[] = {
      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
      { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), },
      { PCI_DEVICE(PCI_VENDOR_ID_DLINK,      0x4300), },
      { PCI_DEVICE(0x16ec,                  0x0116), },
      { PCI_VENDOR_ID_LINKSYS,              0x1032, PCI_ANY_ID, 0x0024, },
      {0,},
};
</pre>


      <B>$ grep -i 0x8139 include/linux/pci_ids.h</B>
Tutti i driver PCI contengono una lista di dispositivi differenti che supportano. Questa lista è contenuta in una struttura di valori <code>struct pci_device_id</code>, come questa. Questo è ciò che dobbiamo guardare per determinare se il nostro dispositivo è supportato da questo driver. Il valore del vendor corrisponde qui, ma il secondo valore dopo il vendor è il valore del dispositivo. Il nostro dispositivo ha il valore 0x8139, mentre questo driver supporta i valori di dispositivi per 0x8169 e 0x8129 con il ''vendor ID'' di <code>PCI_VENDOR_ID_REALTEK</code>. Per cui questo driver non supporterà il nostro dispositivo.
      #define PCI_DEVICE_ID_REALTEK_8139        0x8139
 
 
Questa definizione verrà utile più tardi.
Ora cercate nei file sorgenti dei driver relativi a questo produttore:
 
      <B>$ grep -Rl PCI_VENDOR_ID_REALTEK *</B>
      include/linux/pci_ids.h
      drivers/net/r8169.c
      drivers/net/8139too.c
      drivers/net/8139cp.c
 
Non dobbiamo guardare nel primo file riportato qui, pci_ids.h, dato che è dove abbiamo trovato la definizione originale. Ma i file r8139.c, 8139too.c, e 8169cp.c nella sottodirectory drivers/net/ dovrebbero essere esaminati più da vicino.
Aprite uno di questi dile in un editor e cercate PCI_VENDOR_ID_REALTEK. Nel file drivers/net/r8169.c, si vede nella seguente sezione di codice:
 
      static struct pci_device_id rtl8169_pci_tbl[] = {
              { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
              { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), },
              { PCI_DEVICE(PCI_VENDOR_ID_DLINK,      0x4300), },
              { PCI_DEVICE(0x16ec,                  0x0116), },
              { PCI_VENDOR_ID_LINKSYS,              0x1032, PCI_ANY_ID, 0x0024, },
              {0,},
      };
 
Tutti i driver PCI contengono una lista di dispositivi differenti che supportano. Questa lista è contenuta in una struttura di valori struct pci_device_id, come questa. Questo è ciò che dobbiamo cercare per determinare se il nostro dispositivo è supportato da questo driver. Il valore del vendor corrisponde qui, ma il secondo valore dopo il vendor è il valore di dispositivo. Il nostro dispositivo ha il valore 0x8139, mentre questo driver supporta i valori di dispositivi per 0x8169 e 0x8129 con il vendor ID di PCI_VENDOR_ID_REALTEK. Per cui questo driver non supporterà il nostro dispositivo.
Spostandoci al prossimo file, drivers/net/8139too.c, possiamo trovare la stringa PCI_VENDOR_ID_REALTEK nel seguente pezzo di codice:


Spostandoci al prossimo file, ''drivers/net/8139too.c'', si può trovare la stringa <code>PCI_VENDOR_ID_REALTEK</code> nel seguente pezzo di codice:
<pre>
<pre>
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
Riga 353: Riga 339:
       pdev->vendor, pdev->device, pci_rev);
       pdev->vendor, pdev->device, pci_rev);
   dev_info(&pdev->dev, "Use the \"8139cp\" driver for improved performance and stability.\n");
   dev_info(&pdev->dev, "Use the \"8139cp\" driver for improved performance and stability.\n");
}}
}
</pre>
</pre>


L'utilizzo del valore di PCI_VENDOR_ID_REALTEK qui corrisponde anche con il codice che controlla se il dispositivo PCI ID corrisponde al valore PCI_DEVICE_ID_REALTEK_8139. Se corrisponde, il driver stamperà un messaggio che dice: "Use the 8139cp for improved performance and stability." Forse dovremmo guardare a quel driver di seguito. Anche se non avessimo tale visibile consiglio, il driver 8139too.c non ha la coppia vendor e device ID che stiamo cercando in una variabile del tipo struct pci_device_id, ciò ci dice che non supporta il nostro dispositivo.
L'utilizzo del valore di <code>PCI_VENDOR_ID_REALTEK</code> qui corrisponde anche con il codice che controlla se il dispositivo PCI ID corrisponde al valore <code>PCI_DEVICE_ID_REALTEK_8139</code>. Se corrisponde, il driver stamperà un messaggio che dice: "Use the 8139cp for improved performance and stability." Forse dovremmo guardare a quel driver di seguito. Anche se non avessimo tale visibile consiglio, il driver ''8139too.c'' non ha la coppia vendor e device ID che stiamo cercando in una variabile del tipo <code>struct pci_device_id</code>, ciò ci dice che non supporta il nostro dispositivo.
Infine, guardate nel file drivers/net/8139cp.c. Usa la definizione PCI_VENDOR_ID_REALTEK nel seguente pezzo di codice:


Infine, guardate nel file ''drivers/net/8139cp.c''. Usa la definizione <code>PCI_VENDOR_ID_REALTEK</code> nel seguente sezione di codice:
<pre>
<pre>
static struct pci_device_id cp_pci_tbl[] = {
static struct pci_device_id cp_pci_tbl[] = {
              { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
      { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
              { PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
      { PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
              { },
      { },
    };
};
    MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
</pre>
</pre>


Qui c'è l'uso di entrambi i valori del nostro vendor e device ID in una variabile struct pci_device_id. Questo driver dovrebbe supportare il nostro dispositivo.
Ecco l'uso di entrambi i valori del nostro ''vendor ID'' e ''device ID'' in una variabile <code>struct pci_device_id</code>. Questo driver dovrebbe supportare il nostro dispositivo.
Ora che abbiamo il nome del driver, possiamo lavorare a ritroso, come mostrato nella prima sezione del capitolo, per trovare l'appropriato valore di configurazione del kernel che dovrebbe abilitare la compilazione di questo driver.
 
Riassumendo, qui ci sono i passaggi necessari al fine di trovare quale driver PCI può controllare uno specifico dispositivo PCI:<br>
Ora che abbiamo il nome del driver, possiamo lavorare a ritroso, come mostrato nella prima sezione del capitolo, per trovare l'appropriato valore di configurazione del kernel che dovrebbe essere abilitato per compilare questo driver.
1. Trovate il bus PCI ID del dispositivo pere il quale volete trovare il driver, usate lspci.<br>
 
2. Andate nella directory /sys/bus/pci/devices/0000:bus_id, dove bus_id è il bus PCI trovato nel passaggio precedente.<br>
Riassumendo, ecco i passaggi necessari per trovare quale driver PCI può controllare uno specifico dispositivo PCI:
3 Leggete i valori del vendor e dei file dei dispositivi nella directory dei dispositivi PCI.<br>
# Trovare l'ID del bus PCI del dispositivo per il quale volete trovare il driver, usando ''lspci''.
4. Tornate all'albero sorgente del kernel guardate in include/linux/pci_ids.h per il vendor PCI e device ID trovato nel passaggio precedente.<br>
# Andare nella directory ''/sys/bus/pci/devices/0000:bus_id'', dove ''bus_id'' è l'ID del bus PCI trovato nel passaggio precedente.
5. Cercate nell'albero sorgente del kernel per le referenze a quei valori nei driver. Sia il vendor che il device ID devono essere in una struttura struct pci_device_id.<br>
# Leggere i valori dai file ''vendor'' e ''device'' nella directory dei dispositivi PCI.
6. Cercate nel Makefile del kernel la regola CONFIG_ che compila questo driver usando find e grep:<br>
# Tornare all'albero sorgente del kernel e cercare in ''include/linux/pci_ids.h'' per il ''vendor PCI'' e ''device ID'' trovato nel passaggio precedente.
<B>$ find -type f -name Makefile | xargs grep DRIVER_NAME</B><br>
# Cercare nell'albero sorgente del kernel per le referenze a quei valori nei driver. Sia il ''vendor'' che il ''device ID'' devono essere in una definizione di tipo <code>struct pci_device_id</code>.
7. Cercate nel sistema di configurazione del kernel quel valore di configurazione e andate nel posto di menu che specifica per abilitare il driver da compilare.<br>
# Cercare nei Makefile del kernel la regola <code>CONFIG_</code> che compila questo driver, usando ''find'' e ''grep'': <pre>$ find -type f -name Makefile | xargs grep DRIVER_NAME</pre>
# Cercare nel sistema di configurazione del kernel quel valore di configurazione e andate nella posizione del menù che specifica di abilitare quel driver per essere compilato.


===Dispositivi USB===
===Dispositivi USB===
Trovare il driver specifico per un dispositivo USB è come trovare un driver per un dispositivo PCI come descritto nella precedente sezione, con solo differenze minori nel trovare i valori ID del bus.


Trovare il driver specifico per un dispositivo USB è come trovare un driver per un dispositivo PCI come descritto nella precedente sezione, con solo differenze minori nel trovare il valore di bus ID.
In questo esempio, troviamo il driver che è necessario per un dispositivo USB wireless. Come per l'esempio del dispositivo PCI, i dettagli in questo esempio saranno differenti dalla vostra situazione, ma i passi necessari dovrebbero essere rilevanti per ogni tipo di dispositivo USB per cui desideriate trovare un driver funzionante.
In questo esempio, troviamo il driver che è necessario per un dispositivo USB wireless. Come per l'esempio del dispositivo PCI, i dettagli in questo esempio saranno differenti dalla vostra situazione, ma i passi necessari saranno pertinenti per ogni tipo di dispositivo USB per il quale desiderate trovare un driver funzionante.
Come per il dispositivo PCI, il bus ID deve essere trovato per il dispositivo USB per il quale volete trovare il driver. Per fare ciò,  potete usare il programma lsusb che si trova nel package usbutils.
Il programma lsusb mostra tutti i dispositivi USB attaccati al sistema. Dato che voi non conoscete come il dispositivo specifico che state cercando è chiamato, cominciate a guardare a tutti i dipsoitivi:


    <B>$ /usr/sbin/lsusb</B>
Come per il dispositivo PCI, l'ID del bus deve essere trovato per il dispositivo USB per cui volete trovare il driver. Per fare ciò, potete usare il programma ''lsusb'' che si trova nel pacchetto ''usbutils''.
    Bus 002 Device 003:  ID 045e:0023 Microsoft Corp. Trackball Optical
    Bus 002 Device 001:  ID 0000:0000
    Bus 005 Device 003:  ID 0409:0058 NEC Corp. HighSpeed Hub
    Bus 005 Device 001:  ID 0000:0000
    Bus 004 Device 003:  ID 157e:300d
    Bus 004 Device 002:  ID 045e:001c Microsoft Corp.
    Bus 004 Device 001:  ID 0000:0000
    Bus 003 Device 001:  ID 0000:0000
    Bus 001 Device 001:  ID 0000:0000


I dispositivi con un ID di 0000:0000 possono venir ignorati, dal momento che sono USB host controller che guidano il bus stesso. Filtrandoli ci lascia con quattro dispositivi:
Il programma ''lsusb'' mostra tutti i dispositivi USB attaccati al sistema. Dato che voi non conoscete come il dispositivo specifico che state cercando è chiamato, cominciate guardando tutti i dispositivi:
<pre>
$ /usr/sbin/lsusb
Bus 002 Device 003:  ID 045e:0023 Microsoft Corp. Trackball Optical
Bus 002 Device 001:  ID 0000:0000
Bus 005 Device 003:  ID 0409:0058 NEC Corp. HighSpeed Hub
Bus 005 Device 001:  ID 0000:0000
Bus 004 Device 003:  ID 157e:300d
Bus 004 Device 002:  ID 045e:001c Microsoft Corp.
Bus 004 Device 001:  ID 0000:0000
Bus 003 Device 001:  ID 0000:0000
Bus 001 Device 001:  ID 0000:0000
</pre>


      <B>$ /usr/sbin/lsusb |  grep -v 0000:0000</B>
I dispositivi con un ID di 0000:0000 possono venir ignorati, dal momento che sono ''USB host controller'' che guidano il bus stesso. Filtrandoli, restiamo con quattro dispositivi:
      Bus 002 Device 003:  ID 045e:0023 Microsoft Corp. Trackball Optical
<pre>
      Bus 005 Device 003:  ID 0409:0058 NEC Corp. HighSpeed Hub
$ /usr/sbin/lsusb |  grep -v 0000:0000
      Bus 004 Device 003:  ID 157e:300d
Bus 002 Device 003:  ID 045e:0023 Microsoft Corp. Trackball Optical
      Bus 004 Device 002:  ID 045e:001c Microsoft Corp.
Bus 005 Device 003:  ID 0409:0058 NEC Corp. HighSpeed Hub
Bus 004 Device 003:  ID 157e:300d
Bus 004 Device 002:  ID 045e:001c Microsoft Corp.
</pre>


Dato che i dispositivi USB sono facili da rimuovere, fate l'unplug del dispositivo di cui volete trovare il driver ed eseguite lsusb ancora:
Dato che i dispositivi USB sono facili da rimuovere, scollegate il dispositivo di cui volete trovare il driver ed eseguite ''lsusb'' nuovamente:
 
<pre>
      <B>$ /usr/sbin/lsusb |  grep -v 0000:0000</B>
$ /usr/sbin/lsusb |  grep -v 0000:0000
      Bus 002 Device 003:  ID 045e:0023 Microsoft Corp. Trackball Optical
Bus 002 Device 003:  ID 045e:0023 Microsoft Corp. Trackball Optical
      Bus 005 Device 003:  ID 0409:0058 NEC Corp. HighSpeed Hub
Bus 005 Device 003:  ID 0409:0058 NEC Corp. HighSpeed Hub
      Bus 004 Device 002:  ID 045e:001c Microsoft Corp.
Bus 004 Device 002:  ID 045e:001c Microsoft Corp.
</pre>


Il terzo dispositivo ora manca, che significa il dispositivo mostrato come:
Il terzo dispositivo ora manca, che significa il dispositivo mostrato come:
 
<pre>
  Bus 004 Device 003: ID 157e:300d
Bus 004 Device 003: ID 157e:300d
 
</pre>
è il dispositivo per cui volete trovare il driver.
è il dispositivo per cui volete trovare il driver.


Se voi riattaccate il dispositivo e guardate all'output di lsusb ancora, il numero del dispositivo sarà cambiato:
Se voi riattaccate il dispositivo e guardate all'output di ''lsusb'' ancora una volta, il numero del dispositivo sarà cambiato:
<pre>
/usr/sbin/lsusb | grep 157e
Bus 004 Device 004: ID 157e:300d
</pre>
Questo è dovuto al fatto che i numeri dei dispositivi USB non sono unici, ma cambiano ogni volta che un dispositivo viene inserito. Ciò che resta costante sono il ''vendor ID'' e ''product ID'', mostrati qui da ''lsusb'' come due valori a quattro cifre con un '''<code>:</code>''' tra di loro. Per questo dispositivo, il ''vendor ID'' è '''157e''' e il ''product ID'' è '''300d'''. Scrivetevi i valori che trovate, dato che li userete nei passi successivi.


      <B>/usr/sbin/lsusb | grep 157e</B>
Come per i dispositivi PCI, cercheremo nel codice sorgente del kernel il vendor USB e i product ID per trovare il driver adeguato per controllare questo dispositivo. Sfortunatamente, nessun singolo file contiene tutti gli ID dei vendor USB, come invece per quelli PCI. Perciò è necessaria una ricerca nel codice sorgente dell'intero kernel:
    Bus 004 Device 004: ID 157e:300d
<pre>
$ grep -i -R -l 157e drivers/*
drivers/atm/pca200e.data
drivers/atm/pca200e_ecd.data
drivers/atm/sba200e_ecd.data
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/scsi/ql1040_fw.h
drivers/scsi/ql1280_fw.h
drivers/scsi/qlogicpti_asm.c
</pre>


Questo è dovuto al fatto che i numeri dei dispositivi USB non sono unici, ma cambiano ogni volta che un dispositivo viene inserito dentro. Ciò che è fisso è il vendor e product ID, mostrato qui da lsusb come valore a due quattro cifre con un : tra loro. Per questo dispositivo, il vendo ID e' 157e e il product ID e' 300d. Scrivetevi i valori che trovate dato che li userete nei passi successivi.<br>
Sappiamo che questo è un dispositivo USB wireless, e non un dispositivo ATM o SCSI, per cui possiamo tranquillamente ignorare i file trovati nelle directory ''atm'' e ''scsi''. Quindi resta da cercare solo il file ''drivers/
Come per i dispositivi PCI, cercheremo il codice sorgente del kernel per il vendor USB e per il product IDs per trovare il driver adeguato e controllare questo dispositivo. Sfortunatamente, nessun singolo file contiene tutti gli ID vendor USB, come invece PCI ha. Così una ricerca nel codice sorgente dell'intero kernel è necessaria:
net/wireless/zd1211rw/zd_usb.c''.


      <B>$ grep -i -R -l 157e drivers/*</B>
''zd_usb.c'' mostra la stringa 157e nel seguente pezzo di codice:
       drivers/atm/pca200e.data
<pre>
       drivers/atm/pca200e_ecd.data
static struct usb_device_id usb_ids[]    ={
       drivers/atm/sba200e_ecd.data
      /* ZD1211 */
       drivers/net/wireless/zd1211rw/zd_usb.c
       { USB_DEVICE(0x0ace, 0x1211),  .driver_info =  DEVICE_ZD1211  },
       drivers/scsi/ql1040_fw.h
      { USB_DEVICE(0x07b8, 0x6001),  .driver_info =  DEVICE_ZD1211  },
       drivers/scsi/ql1280_fw.h
      { USB_DEVICE(0x126f, 0xa006),  .driver_info =  DEVICE_ZD1211  },
       drivers/scsi/qlogicpti_asm.c
       { USB_DEVICE(0x6891, 0xa727),  .driver_info =  DEVICE_ZD1211  },
       { USB_DEVICE(0x0df6, 0x9071),  .driver_info =  DEVICE_ZD1211  },
       { USB_DEVICE(0x157e, 0x300b),  .driver_info =  DEVICE_ZD1211  },
       /* ZD1211B */
      { USB_DEVICE(0x0ace, 0x1215),  .driver_info = DEVICE_ZD1211B },
       { USB_DEVICE(0x157e, 0x300d),  .driver_info = DEVICE_ZD1211B },
       {}
};
</pre>


Sappiamo che questo è un dispositivo USB wireless, e non un dispositivo ATM o SCSI, per cui in questo modo noi possiamo sicuramente ignorare i file trovati nelle directory atm e scsi. Quindi resta il file drivers/
Come per i driver PCI, i driver USB dicono al kernel quali dispositivi supportano affinché il kernel possa associare il driver al dispositivo. Ciò viene fatto usando una variabile di tipo <code>struct usb_device_id</code>, come mostrato qui. Questa è una lista dei differenti vendor e product ID che sono supportati da questo driver. La linea:
net/wireless/zd1211rw/zd_usb.c da controllare.
<pre>
zd_usb.c mostra la stringa 157e nel seguente pezzo di codice:
{ USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
</pre>
mostra che il nostro vendor e product ID sono supportati da questo driver.


      static struct usb_device_id usb_ids[]    ={
Una volta che avete il nome del driver che è necessario per controllare il dispositivo, lavorate a ritroso tramite i Makefile del kernel, come descritto precedentemente nel capitolo su come abilitare il driver per compilarlo appropriatamente.
              /* ZD1211 */
              { USB_DEVICE(0x0ace, 0x1211),   .driver_info =  DEVICE_ZD1211  },
              { USB_DEVICE(0x07b8, 0x6001),  .driver_info =  DEVICE_ZD1211  },
              { USB_DEVICE(0x126f, 0xa006),  .driver_info =  DEVICE_ZD1211  },
              { USB_DEVICE(0x6891, 0xa727),  .driver_info =  DEVICE_ZD1211  },
              { USB_DEVICE(0x0df6, 0x9071),  .driver_info =  DEVICE_ZD1211  },
              { USB_DEVICE(0x157e, 0x300b),  .driver_info =  DEVICE_ZD1211  },
              /* ZD1211B */
              { USB_DEVICE(0x0ace, 0x1215),  .driver_info = DEVICE_ZD1211B },
              { USB_DEVICE(0x157e, 0x300d),  .driver_info = DEVICE_ZD1211B },
              {}
      };


Come per i driver PCI, i driver USB dicono al kernel quali dispositivi supportano affinché il kernel possa associare il driver al dispositivo. Ciò viene fatto usando una struct usb_device_id variabile, come mostrato qui. Questa è una lista dei differenti vendor e product ID che sono supportati da questo driver. La linea:
      { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
mostra che il nostro vendor e product ID sono supportati da questo driver.
Una volta che avete il nome del driver che è necessario per controllare il dispositivo, lavorate al contrario attraverso i Makefile del kernel, come descritto precedentemente nel capitolo, su come abilitare il driver per compilarlo appropriatamente.
Riassumendo, i passaggi necessari per trovare quale driver USB controllerà uno specifico dispositivo USB sono:
Riassumendo, i passaggi necessari per trovare quale driver USB controllerà uno specifico dispositivo USB sono:
 
# Trovare il vendor USB e il product ID del dispositivo per il quale si vuole trovare il driver, usando ''lsusb'' dopo aver aggiunto e rimosso il dispositivo per vedere cosa è cambiato nella lista.
1. Trovare il vendor USB e il product ID del dispositivo per il quale volete trovare il driver, usando lsusb dopo aver aggiunto e rimosso il dispositivo per vedere cosa è cambiato nella lista.<br>
# Cercare l'albero del codice sorgente del kernel per il vendor e il product ID del dispositivo USB. Sia il vendor e il product ID dovrebbero essere in una definizione <code>struct usb_device_id</code>.
2. Cercate l'albero del codice sorgente del kernel per il vendor e il product ID del dispositivo USB. Sia il vendor e il product ID dovrebbero essere in una definizione struct usb_device_id.<br>
# Cercare nei Makefile del kernel la regola <code>CONFIG_</code> che compila questi driver, ricorrendo a ''find'' e ''grep'': <pre>$ find -type f -name Makefile | xargs grep DRIVER_NAME</pre>
3. Cercate i Makefile del kernel per la regola CONFIG_ che compila questi driver, usando find e grep:
# Cercare nella configurazione di sistema del kernel il valore di quella configurazione e andate alla posizione nel menù che specifica di abilitare il driver per essere compilato.
 
    <B>$ find -type f -name Makefile | xargs grep DRIVER_NAME</B>
 
4. Cercate nella configurazione di sistema del kernel il valore di quella configurazione e andate alla locazione ,nel menu, specifica per abilitare il driver da compilare.


===Root filesystem===
===Root filesystem===
Il filesystem radice (''root'' NdT) è il filesystem da cui la porzione principale del sistema in esecuzione si avvia. Contiene tutti i programmi iniziali che fanno partire la distribuzione e solitamente contiene anche l'intera configurazione di sistema della macchina. In breve, è molto importante, e deve essere in grado di esser trovato dal kernel a tempo di avvio (''boot time'' NdT) affinché le cose funzionino propriamente.


Il filesystem root è il filesystem dal quale la porzione principale del sistema caricante fa il boot. Contiene tutti i programmi iniziali che fanno partire la distribuzione e solitamente contiene anche l'intero sistema di configurazione per la macchina. In breve, è molto importante, e deve essere capace di esser trovato dal kernel a boot time affinché le cose funzionino propriamente.
Se il vostro nuovo kernel configurato muore a boot time con un errore del tipo:
Se il vostro nuovo kernel configurato muore a boot time con un errore del tipo:
 
<pre>
VFS: Cannot open root device hda2 (03:02)
VFS: Cannot open root device hda2 (03:02)
     Please append a correct "root=" boot option
     Please append a correct "root=" boot option
     Kernal panic: VFS: Unable to mount root fs on 03:02
     Kernal panic: VFS: Unable to mount root fs on 03:02
</pre>
significa che il root filesystem non è stato trovato. Se non state usando un'immagine ramdisk a ''boot time'', è solitamente raccomandabile che compiliate nel kernel sia il filesystem che usate come partizione di root che il controller per quel disco nel kernel, invece di averlo come modulo. Se invece usate un ramdisk a boot time, dovreste essere coperti anche compilando queste porzioni come moduli.
::[[Immagine:Warning_65x68.jpg|left]]Come potete determinare se state usando un ramdisk a boot time? Nel [[LKN:_Installare_ed_Avviare_con_un_Kernel|Capitolo 5]] abbiamo menzionato l'uso dello script di installazione della vostra distribuzione per installare il kernel rispetto all'effettuare l'installazione per proprio conto. Se state usando lo script di installazione della distribuzione, state probabilmente già usando un ramdisk. Se invece lo state installando per vostro conto, probabilmente non lo state usando.


significa che il root filesystem non e' stato trovato. Se non state usando una immagine ramdisk a boot time, è solitamente raccomandabile che compiliate sia il filesystem che usate come partizione di root, e il disk controller per quel disco, nel kernel, invece di averlo come modulo. Se usate un ramdisk a boot time, voi dovreste di sicuro compilare queste porzioni come moduli.
Le sottosezioni seguenti mostrano come lasciare che il kernel trovi il root filesystem durante il boot.
::[[Immagine:Warning_65x68.jpg|left]]Come potete determinare se state usando un ramdisk a boottime? Nel capitolo 5 abbiamo menzionato l'uso dell'installation script della distribuzione per installare il kernel contro il fare l'installazione per proprio conto. Se state usando l'installation script della distribuzione, state probabilmente usando un ramdisk. se lo state installando per vostro conto, probabilmente non lo state usando.
Le seguenti sottosezioni mostrano come lasciare che il kernel trovi il root filesystem durante il boot.


====Tipo del filesystem====
====Tipo del filesystem====
 
Per prima cosa, bisogna determinare il tipo di filesystem che la partizione di root sta utilizzando. Per fare ciò, si guardi al risultato del comando ''mount'':
Primo, il tipo di filesystem che la partizione di root sta usando necessita di esser determinata. Per fare ciò, guardate nell'output del comando di mount:
<pre>
 
$ mount | grep " / "
$mount |grep " / "
/dev/sda2 on / type ext3 (rw,noatime)
/dev/sda2 on / type ext3 (rw,noatime)
</pre>
 
Siamo interessati al tipo di filesystem, che viene mostrato dopo la parola <code>type</code>. In questo esempio è ext3. Questo è il tipo di filesystem che la partizione di root sta usando. Andate nel sistema di configurazione del kernel e siate sicuri che questo tipo di filesystem sia abilitato, come descritto nel [[LKN:_Ricette_per_Configurare_il_Kernel|Capitolo 8]].
Siamo interessati al tipo di filesystem, che viene mostrato dopo la parola type. In questo esempio, è ext3. Questo è il tipo di filesystem che la partizione di root sta usando. Andate nel sistema di configurazione del kernel e siate sicuri che questo tipo di filesystem sia abilitato, come descritto ne lCapitolo 8.


====Controller del disco====
====Controller del disco====
Nell'output del comando ''mount'' appena mostrato, la prima porzione della linea mostra su quale dispositivo a blocchi il root filesystem è montato. In questo esempio è ''/dev/sda2''. Ora che il filesystem è correttamente configurato nel vostro kernel, dovete essere sicuri che questo dispositivo a blocchi funzionerà correttamente. Per trovare quali driver sono necessari, ancora una volta bisognerà guardare in ''sysfs''.


Nell'output del comando appena mostrato, la prima porzione di linea mostra su quale dispositivo a blocchi il root filesystem è montato. In questo esempio, è /dev/sda2. Ora che il filesystem è correttamente configurato nel vostro kernel, dovete essere sicuri che questo dispositivo a blocchi funzionerà correttamente. Per trovare quali driver sono necessari per questo, dovete guardare in sysfs ancora.
Tutti i dispositivi a blocchi sono mostrati in ''sysfs'' in ''/sys/block'' oppure in ''/sys/class/block'', a seconda della versione del kernel che state usando. In entrambi i luoghi, i dispositivi a blocchi costituiscono un albero, con le diverse partizioni figlie del dispositivo principale:
Tutti i dispositivi a blocchi mostrati in sysfs sia in /sys/block o in /sys/class/block, dipendono dalla versione del kernel che state usando. In entrambi i posti, i dispositivi a blocchi sono un albero, con le partizioni differenti essendo figli del dispositivo principale:
<pre>
$ tree -d /sys/block/ | egrep "hd|sd"
|-- hdc
|-- hdd
`-- sda
|-- sda1
|-- sda2
|-- sda3
</pre>
Data l'informazione nel comando di ''mount'', dovete essere sicuri che il dispositivo sda2 è configurato correttamente. Poiché questa è una partizione (le partizioni di un disco sono numerate, mentre i dispositivi a blocchi principali non lo sono), l'intero dispositivo sda deve essere configurato. (Senza il dispositivo a blocchi principale, non c'è possibilità di accedere alle partizioni individuali su quel dispositivo).


$ tree -d /sys/block/ | egrep "hd|sd"
Il dispositivo a blocchi sda è rappresentato semplicemente come il dispositivo di rete che abbiamo visto precedentemente in questo capitolo. Esiste un symlink nella directory del dispositivo chiamato ''device'' che punta al dispositivo logico che controlla il dispositivo a blocchi:
|-- hdc
<pre>
|-- hdd
$ ls -l /sys/block/sda
`-- sda  |-- sda1
...
  |-- sda2  |-- sda3
device -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0
 
...
Data l'informazione nel comando di mount, dovete essere sicuri che il dispositivo sda2 è configurato correttamente. Poiché questa è una partizione (le partizioni di un disco sono numerate, mentre i dispositivi a blocchi principali non lo sono), l'intero dispositivo sda deve essere configurato. (Senza il dispositivo a blocchi principale, non c'è possibilità di accedere alle partizioni individuali su quel dispositivo).
</pre>
Il dispositivo a blocchi sda è rappresentato semplicemente come il dispositivo di rete che abbiamo visto precedentemente in questo capitolo. Esiste un symlink nella directory del dispositivo chiamato device che punta al dispositivo logico che controlla il dispositivo a blocchi:
Ora avete bisogno di iniziare a percorrere la catena dei dispositivi nel ''sysfs'' per trovare quale driver sta controllando questo dispositivo:
 
<pre>
$ ls -l /sys/block/sda
$ ls -l /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0
...
...
device -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0
driver -> ../../../../../../bus/scsi/drivers/sd
...
...
 
</pre>
Ora avete bisogno di iniziare a scorrere la catena dei sispositivi nel sysfs per trovare quale driver sta controllando questo dispositivo:
Qui vediamo che il driver del controller del disco SCSI è responsabile per il funzionamento di questo dispositivo. Così sappiamo che dobbiamo configurare il supporto ai dischi SCSI nella nostra configurazione del kernel.
 
$ ls -l /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0
...
driver -> ../../../../../../bus/scsi/drivers/sd
...
 
Qui vediamo che il driver del controller del disco SCSI è responsabile per il funzionamento di questo dispositivo. Così sappiamo che dobbiamo configurare il supporto ai dischi SCSI nella nostra configurazione del kernel. Continuando a salire la catena delle directory in sysfs, provate a trovare dove è il driver che controlla l'hardware:
 
$ ls -l /sys/devices/pci0000:00/0000:00:1f.2/host0
...


Continuando a salire la catena delle directory in ''sysfs'', provate a trovare dov'è il driver che controlla l'hardware:
<pre>
$ ls -l /sys/devices/pci0000:00/0000:00:1f.2/host0
...
</pre>
Ancora, nessun driver qui. Continuando di un livello in su:
Ancora, nessun driver qui. Continuando di un livello in su:
<pre>
$ ls -l /sys/devices/pci0000:00/0000:00:1f.2
...
driver -> ../../../bus/pci/drivers/ata_piix
</pre>
Eccolo! Questo è il controller del disco che abbiamo bisogno di assicurarci sia nella nostra configurazione del kernel.


$ ls -l /sys/devices/pci0000:00/0000:00:1f.2
Così per questo root filesystem, abbiamo bisogno di abilitare i driver ext3, sd, e ata_piix nella nostra configurazione del kernel, così che saremo capaci di fare il boot con successo del nostro kernel su questo hardware.
...
driver -> ../../../bus/pci/drivers/ata_piix


Ecco! Questo è il controller del disco di cui abbiamo bisogno da assicurare che sia nella nostra configurazione del kernel.
===Script d'aiuto===
Così per questo root filesystem, abbiamo bisogno di abilitare l'ext3, sd, e ata_piix driver nella nostra configurazione del kernel così che saremo capaci di fare il boot con successo del nostro kernel su questo hardware.
Come menzionato all'inizio del capitolo, file e directory in ''sysfs'' cambiano da una versione del kernel a un'altra. Qui c'è uno script che è a portata di mano per determinare i necessari driver del kernel e il nome del modulo per ogni dispositivo nel sistema. È stato sviluppato con gli sviluppatori del kernel responsabili per ''sysfs'' e dovrebbe funzionare con successo con tutte le versioni future del kernel 2.6 .


===Un aiuto dallo script===
Per esempio, liquida il precedente esempio, quando dovevate prendere tutti i driver appropriati per i dispositivi a blocco sda:
<pre>
$ get-driver.sh sda
looking at sysfs device: /sys/devices/pci0000:00/0000:00:1f.2/host0/
target0:0:0/0:0:0:0
found driver: sd
found driver: ata_piix
</pre>
Posso anche trovare tutto sui driver appropriati necessari per cose complicate come i dispositivi USB-to-serial:
<pre>
$ get-driver.sh ttyUSB0
looking at sysfs device: /sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2.
3/4-2.3:1.0/ttyUSB0
found driver: pl2303 from module: pl2303
found driver: pl2303 from module: pl2303
found driver: usb from module: usbcore
found driver: usb from module: usbcore
found driver: usb from module: usbcore
found driver: uhci_hcd from module: uhci_hcd
</pre>


Come menzionato all'inizio del capitolo, file e directory nel sysfs cambiano da una versione del kernel a un altra. Qui c'è uno script che è alla portata di mano per determinare il driver del kernel necessario e il module name per ogni dispositivo nel sistema. E' stato sviluppato con gli sviluppatori del kernel responsabili per il sysfs e dovrebbe funzionare con successo con tutte le versioni future del kernel 2.6 .
Potete scaricare un file di esempio contenente questo script dal web site del libro, fornito nella sezione "How to Contact Us" nella Prefazione.
Per esempio, fa un "short work" del precedente esempio, quando dovete prendere tutti i driver appropriati per i dispositivi a blocco sda:


<strong>$ get-driver.sh sda</strong>
Di seguito lo script:
looking at sysfs device: /sys/devices/pci0000:00/0000:00:1f.2/host0/
<pre>
target0:0:0/0:0:0:0
#!/bin/sh
found driver: sd
#
found driver: ata_piix
# Find all modules and drivers for a given class device.
 
#
Posso anche trovare tutto sui driver appropriati necessari per cose complicate come i dispositivi USB-toserial:
if [ $# != "1" ] ; then
 
echo
<strong>$ get-driver.sh ttyUSB0</strong>
echo "Script to display the drivers and modules for a specified sysfs
looking at sysfs device: /sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2.
class device"
3/4-2.3:1.0/ttyUSB0
echo "usage: $0 <CLASS_NAME>"
found driver: pl2303 from module: pl2303
echo
found driver: pl2303 from module: pl2303
echo "example usage:"
found driver: usb from module: usbcore
echo " $0 sda"
found driver: usb from module: usbcore
echo "Will show all drivers and modules for the sda block device."
found driver: usb from module: usbcore
echo
found driver: uhci_hcd from module: uhci_hcd
exit 1
 
fi
Potete scaricare un file di esempio contenente questo script dal web site del libro, fornito nella sezione "How to Contact Us" in Preface.
DEV=$1
 
if test -e "$1"; then
#!/bin/sh
DEVPATH=$1
#
else
# Find all modules and drivers for a given class device.
# find sysfs device directory for device
#
DEVPATH=$(find /sys/class -name "$1" | head -1)
if [ $# != "1" ] ; then<br>
test -z "$DEVPATH" && DEVPATH=$(find /sys/block -name "$1" | head -1)
  echo<br>
test -z "$DEVPATH" && DEVPATH=$(find /sys/bus -name "$1" | head -1)
  echo "Script to display the drivers and modules for a specified sysfs
if ! test -e "$DEVPATH"; then
  class device"
   echo "no device found"
  echo "usage: $0 <CLASS_NAME>"
  echo
  echo "example usage:"
  echo " $0 sda"
  echo "Will show all drivers and modules for the sda block device."
   echo
   exit 1
   exit 1
  fi
  fi
DEV=$1
fi
if test -e "$1"; then
echo "looking at sysfs device: $DEVPATH"
  DEVPATH=$1
if test -L "$DEVPATH"; then
  else
# resolve class device link to device directory
  # find sysfs device directory for device
DEVPATH=$(readlink -f $DEVPATH)
  DEVPATH=$(find /sys/class -name "$1" | head -1)
  echo "resolve link to: $DEVPATH"
   test -z "$DEVPATH" && DEVPATH=$(find /sys/block -name "$1" | head -1)
fi
  test -z "$DEVPATH" && DEVPATH=$(find /sys/bus -name "$1" | head -1)
if test -d "$DEVPATH"; then
   if ! test -e "$DEVPATH"; then
# resolve old-style "device" link to the parent device
   echo "no device found"
PARENT="$DEVPATH";
  exit 1
while test "$PARENT" != "/"; do
   if test -L "$PARENT/device"; then
  DEVPATH=$(readlink -f $PARENT/device)
  echo "follow 'device' link to parent: $DEVPATH"
  break
  fi
  PARENT=$(dirname $PARENT)
done
fi
while test "$DEVPATH" != "/"; do
DRIVERPATH=
DRIVER=
MODULEPATH=
MODULE=
if test -e $DEVPATH/driver; then
  DRIVERPATH=$(readlink -f $DEVPATH/driver)
  DRIVER=$(basename $DRIVERPATH)
  echo -n "found driver: $DRIVER"
   if test -e $DRIVERPATH/module; then
  MODULEPATH=$(readlink -f $DRIVERPATH/module)
  MODULE=$(basename $MODULEPATH)
   echo -n " from module: $MODULE"
   fi
   fi
  echo
  fi
  fi
  echo "looking at sysfs device: $DEVPATH"
  DEVPATH=$(dirname $DEVPATH)
if test -L "$DEVPATH"; then
done
  # resolve class device link to device directory
</pre>
  DEVPATH=$(readlink -f $DEVPATH)
  echo "resolve link to: $DEVPATH"
fi
if test -d "$DEVPATH"; then
  # resolve old-style "device" link to the parent device
  PARENT="$DEVPATH";
  while test "$PARENT" != "/"; do
  if test -L "$PARENT/device"; then
    DEVPATH=$(readlink -f $PARENT/device)
    echo "follow 'device' link to parent: $DEVPATH"
    break
  fi
  PARENT=$(dirname $PARENT)
  done
fi
while test "$DEVPATH" != "/"; do
  DRIVERPATH=
  DRIVER=
  MODULEPATH=
  MODULE=
  if test -e $DEVPATH/driver; then
  DRIVERPATH=$(readlink -f $DEVPATH/driver)
  DRIVER=$(basename $DRIVERPATH)
  echo -n "found driver: $DRIVER"
  if test -e $DRIVERPATH/module; then
    MODULEPATH=$(readlink -f $DRIVERPATH/module)
    MODULE=$(basename $MODULEPATH)
    echo -n " from module: $MODULE"
  fi
  echo
  fi
  DEVPATH=$(dirname $DEVPATH)
done
 


----
----
Riga 631: Riga 634:
----
----


[http://www.kernel.org/pub/linux/kernel/people/gregkh/lkn/lkn_pdf/ch07.pdf ''Capitolo originale'']
 
[http://files.kroah.com/lkn/lkn_pdf/ch07.pdf ''Capitolo originale'']




[[Categoria:Documentazione tecnica]]
[[Categoria:Documentazione tecnica]]
[[Categoria:Linux Kernel in a Nutshell]]
[[Categoria:Linux Kernel in a Nutshell]]
3 581

contributi