Product SiteDocumentation Site

8.10. Compilare un kernel

I kernel forniti da Debian includono il maggior numero possibile di funzionalità, così come il massimo numero di driver, per coprire lo spettro più ampio di configurazioni hardware esistenti. Ecco perché alcuni utenti preferiscono ricompilare il kernel per includere unicamente ciò di cui necessitano. Ci sono due ragioni per questa scelta. Primo, questo può ottimizzare il consumo di memoria perché il codice del kernel anche se non viene mai utilizzato occupa memoria senza motivo (e non viene mai posto nello spazio di swap, dato che utilizza la vera RAM), cosa che può diminuire le prestazioni complessive del sistema. Inoltre un kernel compilato localmente può anche limitare i rischi di sicurezza poiché solo una frazione del codice del kernel è compilato ed eseguito.
Ricompilare il kernel è inoltre necessario se si vuole utilizzare certe funzionalità che sono disponibili solo come patch (e non sono incluse nella versione standard del kernel).

8.10.1. Introduzione e prerequisiti

Debian gestisce il kernel sotto forma di pacchetti, diversamente da come i kernel sono stati compilati ed installati tradizionalmente. Strumenti specifici sono stati sviluppati per questo motivo. Consentono la creazione facilitata di pacchetti Debian a partire dai sorgenti del kernel Linux, eventualmente aggiungendo patch lungo la strada. Poiché il kernel rimane sotto il controllo del sistema di pacchettizazione può essere rimosso in modo pulito o implementato in diverse macchine. Inoltre gli script associati con questi pacchetti automatizzano l'interazione con il bootloader.
Per compilare un kernel Linux nello stile Debian è necessario usare gli strumenti inclusi nel pacchetto kernel-package. Inoltre i passaggi di configurazione del kernel richiedono il pacchetto libncurses5-dev. Infine il pacchetto fakeroot consente la creazione del pacchetto Debian senza l'impiego di privilegi di amministrazione.

8.10.2. Ottenere i sorgenti

Come qualiasi cosa che può essere utile in un sistema Debian, i sorgenti del kernel Linux sono disponibili in un pacchetto. Per ottenerli basta installare il pacchetto linux-source-versione. Il comando apt-cache search ^linux-source elenca le varie versioni del kernel pacchettizate da Debian. L'ultima versione è disponibile nella distribuzione Unstable: è possibile ottenerla senza troppi rischi (specialmente se il proprio APT è configurato secondo le istruzioni nella Sezione 6.2.6, «Lavorare con più distribuzioni»). Va notato che il codice sorgente contenuto in questi pacchetti non corrisponde precisamente con quello pubblicato da Linus Torvalds e dagli sviluppatori del kernel: come tutte le distribuzioni Debian applica una serie di patch. Queste modifiche includono patch (alcune collegate a problemi di sicurezza) che sono in attesa di essere incluse nella versione successiva del kernel, così come alcune funzionalità che sono specifiche di Debian (come cramfs, un filesystem specifico per l'immagine initrd).
Il resto di questa sezione si concentra sulla versione 2.6.32 del kernel Linux ma gli esempi possono natualmente essere adattati alla particolare versione del kernel che si desidera.
Assumiamo che il pacchetto linux-source-2.6.32 sia installato. Contiene /usr/src/linux-source-2.6.32.tar.bz2, un archivio compresso dei sorgenti del kernel. Si devono estrarre questi file in una nuova directory (non direttamente in /usr/src/ poiché non c'è bisogno di permessi speciali per compilare un kernel Linux): ~/kernel/ è sufficiente.
$ mkdir ~/kernel; cd ~/kernel
$ tar -xjf /usr/src/linux-source-2.6.32.tar.bz2

8.10.3. Configurare il kernel

I passi successivi consistono nella configurazione del kernel secondo le proprie necessità. La procedura esatta dipende dagli obiettivi.
Quando si ricompila una versione del kernel più recente (eventualmente con patch aggiuntive) la configurazione sarà probabilmente mantenuta più simile possibile a quella proposta da Debian. In questo caso, e piuttosto di riconfigurare tutto da zero, è sufficiente copiare il file /boot/config-versione (la versione è quella del kernel correntemente in uso, che può essere trovato con il comando uname -r) in un file .config nella directory contenente i sorgenti del kernel.
$ cp /boot/config-2.6.32-5-686 ~/kernel/linux-source-2.6.32/.config
Se non si necessita di cambiare la configurazione è possibile fermarsi qui e saltare alla prossima sezione. Se invece è necessario modificarla, o se si è deciso di riconfigurare tutto da zero, è necessario prendersi il tempo di configurare il kernel. Ci sono varie interfacce dedicate nella directory dei sorgenti del kernel che possono essere richiemate utilizzando il comando make target dove target sarà uno dei valori descritti di seguito.
make menuconfig compila ed esegue un'interfaccia testuale (ecco perché il pacchetto libncurses5-dev è richiesto) che consente la navigazione tra le opzioni disponibili in una struttura gerarchica. La pressione del tasto Spazio cambia il valore delle opzioni selezionate, Invio conferma il bottone selezionato in basso sullo schermo, Select rimanda al sotto-menu selezionato, Exit chiude la finestra corrente e torna indietro nella gerarchia, Help visualizzarà informazioni maggiormente dettagliate sul ruolo dell'opzione selezionata. Le frecce consentono di muoversi tra la lista di opzioni ed i bottoni. Per uscire dal programma di configurazione scegliere Exit dal menu principale. Il programma offrirà di salvare le modifiche effettuate: accettare se si è soddisfatti delle proprie scelte.
Altre interfacce hanno funzioni simili, ma lavorano con interfacce grafiche più moderne: make xconfig usa l'interfaccia grafica Qt e make gconfig usa GTK+. La prima richiede libqt3-mt-dev, la seconda dipende da libglade2-dev e libgtk2.0-dev.
Il comando make-kpkg, presentato nel prossimo paragrafo, esegue make oldconfig automaticamente per assicurarsi che sia presente una configurazione del kernel. Questo metodo di configurazione riutilizza semplicemente le scelte salvate nel file .config. Se non c'è alcun file si comporta come make config, un'interfaccia testuale che pone tutte le domande (diverse centinaia) una alla volta. Se il file .config esiste ma non menziona tutte le opzioni esistenti, allora questo metodo pone unicamente le domande per le quali il file non contiene una risposta.

8.10.4. Compilazione e creazione del pacchetto

Quando la configurazione del kernel è pronta, il comando make-kpkg fornito da Debian compila il kernel, quindi genera il corrispondente pacchetto (o i pacchetti) Debian. Proprio come make, anche make-kpkg prende il nome dell'obiettivo da eseguire come un argomento: kernel-image genera un pacchetto kernel compilato, kernel-doc un pacchetto contenente documentazione inclusa con il kernel, kernel-headers un pacchetto con i file header del kernel (file .h per il kernel nella directory include/ che sono utili per la compilazione di moduli esterni) e kernel-source crea un pacchetto contenente i sorgenti del kernel.
make-kpkg accetta inoltre altri parametri: --append-to-version suffisso aggiunge suffisso al nome del kernel: il suffisso è inoltre incluso nel nome del pacchetto. --revision revisione definisce il numero di versione del pacchetto generato. Debian usa certi suffissi per identificare i kernel standard, compilati specificatamente per un dato processore, oppure con certe opzioni (-486, -686, -686-bigmem, -amd64, -vserver-686, -vserver-686-bigmem, -openvz-686, -xen-686). È meglio evitare questi suffissi per i pacchetti locali, così possono essere facilmente distinti dai pacchetti ufficiali prodotti dal progetto Debian.
Il programma make-kpkg quando crea il pacchetto Debian esegue azioni normalmente consentite solo all'utente root; tuttavia può essere ingannato per lavorare con l'identità di un utente normale con il comando fakeroot (si veda il riquadro STRUMENTO fakeroot).
$ fakeroot make-kpkg --append-to-version -falcot --revision 1 --initrd kernel-image 
[...]
$ ls ../*.deb
../linux-image-2.6.32-falcot_1_i386.deb
Come si può vedere il pacchetto viene creato con il nome «linux-image-2.6.32-falcot_1_i386.deb».

8.10.5. Compilare moduli esterni

Alcuni moduli sono mantenuti fuori dal kernel ufficiale Linux. Per usarli è necessario compilarli parallelamente al kernel corrispondente. Alcuni moduli comuni di terze parti sono forniti da Debian in pacchetti dedicati: lustre-source per il filesystem Lustre, qc-usb-source per i driver di alcune webcam USB (Logitech QuickCam Express), ecc.
Questi pacchetti esterni sono molti e variegati e non possiamo elencarli tutti qui: il comando apt-cache search source$ può restringere il campo alla chiave di ricerca. Comunque una lista completa non sarebbe particolarmente utile visto che non c'è una ragione particolare per compilare moduli esterni se non quando si sa di averne bisogno. In questi casi la documentazione del dispositivo dettaglia tipicamente i moduli specifici di cui necessita per funzionare su Linux.
Per esempio, si osservi il pacchetto qc-usb-source: dopo l'installazione un .tar.gz dei sorgenti del modulo viene depositato in /usr/src/. Questi sorgenti devono essere estratti nella directory di lavoro:
$ cd ~/kernel/
$ tar xjf /usr/src/qc-usb.tar.bz2
$ ls modules/
qc-usb
I sorgenti del modulo sono ora posizionati nella directory ~/kernel/modules/qc-usb/. Per compilare questi moduli e creare un pacchetto Debian bisogna lanciare make-kpkg con l'obiettivo modules-image ed indicare la posizione dei moduli attraverso la variabile d'ambiente MODULE_LOC (senza questa variabile sarebbe utilizzato /usr/src/modules/, ma non funzionerebbe nel nostro caso). In via predefinita il comando prova a creare i pacchetti per tutti i moduli esterni che sono stati estratti in quella posizione. L'opzione --added-modules consente di scegliere esplicitamente i moduli esterni da compilare. Per elencarne più d'uno è sufficiente separarli con una virgola.
$ export MODULE_LOC=~/kernel/modules
$ cd ~/kernel/linux-source-2.6.32
$ fakeroot make-kpkg --append-to-version -falcot modules-image
[...]
Module /home/roland/kernel/modules/qc-usb processed fine
$ ls ../*.deb
../linux-image-2.6.32-falcot_1_i386.deb
../qc-usb-modules-2.6.32-falcot_0.6.6-7+1_i386.deb

8.10.6. Applicare una patch al kernel

Alcune funzionalità non sono incluse nel kernel standard perché non mature o per un mancato accordo tra il manutentore del codice sorgente ed i manutentori del kernel. Alcune funzionalità possono essere distribuite come patch che chiunque può applicare liberamente ai sorgenti del kernel.
Debian distribuisce alcune di queste patch nei pacchetti linux-patch-* o kernel-patch-* (per esempio linux-patch-grsecurity2 intensifica alcune delle politiche di sicurezza del kernel). Questi pacchetti installano file nella directory /usr/src/kernel-patches/.
Per applicare una o più di queste patch installate utilizzare il comando patch nella directory dei sorgenti, poi avviare la compilazione del kernel come descritto sopra.
$ cd ~/kernel/linux-source-2.6.32
$ fakeroot make-kpkg clean
$ zcat /usr/src/kernel-patches/diffs/grsecurity2/grsecurity-2.1.14-2.6.32.13-201005151340.patch.gz | patch -p1
$ fakeroot make-kpkg --append-to-version -grsec --revision 1 --initrd kernel-image
$ ls ../*.deb
../linux-image-2.6.32-falcot_1_i386.deb
../qc-usb-modules-2.6.32-falcot_0.6.6-7+1_i386.deb
../linux-image-2.6.32-grsec_1_i386.deb
Notare che una patch potrebbe non funzionare con ogni versione del kernel: è possibile che patch fallisca quando la applica ai sorgenti del kernel. Un messaggio d'errore sarà visualizzato e fornirà alcuni dettagli a proposito del fallimento. In questo caso, si deve far riferimento alla documentazione disponibile nel pacchetto Debian della patch (nella directory /usr/share/doc/linux-patch-*/). In molti casi il manutentore indica per quali versioni del kernel è stata realizzata la patch.