Compilare un kernel linux

La compilazione del kernel è un passaggio importante per molti sistemi Linux.
Oltre ai vantaggi di performance che derivano dalla customizzazzione del kernel si possono evitare possibili problemi di sicurezza legati a features che non sono indispensabili per l'erogazione del servizio oppure al semplice funzionamento di un device particolare.
Di fatto, seppur non indispensabile, è sempre raccomandabile la ricompilazione di un kernel su un server destinato ad andare in produzione ed essere accessibile via Internet.

I passaggi per la compilazione di un kernel sono relativamente semplici e schematici:
Download e scompattazione dei sorgenti; configurazione; compilazione; installazione del kernel.

- DOWNLOAD DEI SORGENTI O DELLE PATCH
Il sito ufficiale per il kernel linux è http://www.kernel.org, dove si ha la possibilità di scaricare i sorgenti del kernel nelle sue varie versioni. Si può scaricare l'intero file dei sorgenti con documentazione che si presenta come un  tar.gz o tar.bz2 di 20-30 Mbyte, oppure scaricare solo le patch, di dimensioni molto minori, che, di versione in versione, contengono solo le differenze nei sorgenti.

- SCOMPATTARE IL TARBALL SCARICATO
La directory in cui scompattarlo è /usr/src. E' necessario avere l'ambiente di compilazione in /usr/src/linux, per cui si usa, generalmente, creare un link simbolico di nome /usr/src/linux che punta alla directory che contiene effettivamente i sorgenti del kernel (es: ln -s /usr/src/linux-2.4.18 /usr/src/linux). Cambiando il puntamento del symlink /urc/src/linux è possibile passare velocemente a compilare kernel di diverse versioni.

- APPLICAZIONE DELLE EVENTUALI PATCH
In questo caso verrà applicata la patch 2.4.19 per patchare il kernel 2.4.18
[root@dido linux]# cat ../patch-2.4.19 | patch -p1
patching file COPYING
patching file CREDITS
patching file Documentation/Changes
patching file Documentation/Configure.help
[...]


- PULIZIA DEI SORGENTI
E' un operazione richiesta ogni volta che si compilano dei sorgenti precedentementa già compilati.
[root@dido linux]# make clean
make[1]: Entering directory `/usr/src/linux-2.4.17/arch/i386/boot'
rm -f tools/build
rm -f setup bootsect zImage compressed/vmlinux.out
[...]
rm -f procfs_example.sgml
make[1]: Leaving directory `/usr/src/linux-2.4.17/Documentation/DocBook'


- CONFIGURAZIONE DEL NUOVO KERNEL
Ci sono diverse interfacce per configurare il kernel. Il comando più utilizzato è make menuconfig, ma se si ha  una macchina con X attivato  si ha la possibilità di utilizzare un frontend grafico con il comando make xconfig, altrimenti si ha la possibilità di utilizzare un comando make config per utilizzare un front-end del tutto testuale.

[root@dido linux] make menuconfig
rm -f include/asm
( cd include ; ln -sf asm-i386 asm)
make -C scripts/lxdialog all
make[1]: Entering directory `/usr/src/linux-2.4.17/scripts/lxdialog'
make[1]: Leaving directory `/usr/src/linux-2.4.17/scripts/lxdialog'
/bin/sh scripts/Menuconfig arch/i386/config.in
Using defaults found in .config
Preparing scripts: functions, parsing........................................................................done.


[root@dido linux] make xconfig
rm -f include/asm
( cd include ; ln -sf asm-i386 asm)
make -C scripts kconfig.tk
make[1]: Entering directory `/usr/src/linux-2.4.17/scripts'
gcc -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -c -o tkparse.o tkparse.c
gcc -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -c -o tkcond.o tkcond.c
gcc -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -c -o tkgen.o tkgen.c
gcc -o tkparse tkparse.o tkcond.o tkgen.o
cat header.tk >> ./kconfig.tk
./tkparse < ../arch/i386/config.in >> kconfig.tk
echo "set defaults \"arch/i386/defconfig\"" >> kconfig.tk
echo "set ARCH \"i386\"" >> kconfig.tk
cat tail.tk >> kconfig.tk
chmod 755 kconfig.tk
make[1]: Leaving directory `/usr/src/linux-2.4.17/scripts'
wish -f scripts/kconfig.tk


[root@dido linux]# make config
rm -f include/asm
( cd include ; ln -sf asm-i386 asm)
/bin/sh scripts/Configure arch/i386/config.in
#
# Using defaults found in .config
#
*
* Code maturity level options
*
Prompt for development and/or incomplete code/drivers (CONFIG_EXPERIMENTAL) [Y/n/?]
[...]


Dopo aver configurato le singole componenti del kernel da attivare (è la fase più importante, in quanto una errata scelta può portare al blocco del sistema al reboot o al mancato supporto di alcuni device della propria macchina) si ha la possibilità di salvare la propria configurazione su un file alternativo, altrimenti quando si esce dal menu di configurazione verrà chiesto di salvare la configurazione in .config, file di default per la compilazione del kernel.

- MODIFICA DEL MAKEFILE - Solo se si usa make install per l'installazione automatica del kernel
Per semplificare le operazioni dell'installazione dell'immagine del kernel è sufficiente scommentare la seguente riga nel makefile, per ritrovarsi la copia dell'immagine e dei file relativi indispensabili al boot nel PATH configurato (abbinato al comando make install):
# INSTALL_PATH specifies where to place the updated kernel and system map
# images.  Uncomment if you want to place them anywhere other than root.
export INSTALL_PATH=/boot

Se questa operazione non viene fatta i file compilati del nuovo kernel dovranno essere spostati a mano, secondo le indicazioni sotto riportate.
E' possibile inoltre aggiungere una EXTRAVERSION che permette di identificare compilazioni dello stesso kernel ma con configurazioni diverse.
EXTRAVERSION =-SARUMAN

- COMPILAZIONE DEI SORGENTI
Eseguire in sequenza i seguenti comandi:
make dep Crea le dipendenze per la compilazione dei sorgenti
make clean Esegue un clean
make bzImage Crea l'immagine del kernel che verra' caricata al boot
make modules Compila i moduli
make modules_install Copia i moduli in /lib/modules/$KERNEL_VERSION

- INSTALLAZIONE DEL NUOVO KERNEL
Eseguite tutte le operazioni per la compilazione si deve installare l'immagine del kernel, si hanno due alternative:
Manuale
All'interno della directory, /usr/src/linux/arch/$arch/boot/ si avrà l'immagine del kernel (Il file bzImage) la quale dovrà essere copiata manualmente in /boot possibilmente con un nuovo nome per evitare sovrascrizioni nelle prossime compilazioni.
Dove $arch corrisponde al nome dell'architettura del sistema  per cui e' stato compilato il kernel:
neo@eva:~$ls -l /usr/src/linux/arch/
total 72
drwxr-xr-x   7 root root 4096 2004-02-23 11:13 alpha
drwxr-xr-x  21 root root 4096 2004-02-23 11:13 arm
drwxr-xr-x   7 root root 4096 2004-02-23 11:13 cris
drwxr-xr-x   7 root root 4096 2004-02-23 11:13 i386
drwxr-xr-x  14 root root 4096 2004-02-23 11:13 ia64
drwxr-xr-x  20 root root 4096 2004-02-23 11:13 m68k
drwxr-xr-x  34 root root 4096 2004-02-23 11:13 mips
drwxr-xr-x   6 root root 4096 2004-02-23 11:13 mips64
drwxr-xr-x   8 root root 4096 2004-02-23 11:13 parisc
drwxr-xr-x  13 root root 4096 2004-02-23 11:13 ppc
drwxr-xr-x   8 root root 4096 2004-02-23 11:13 ppc64
drwxr-xr-x   7 root root 4096 2004-02-23 11:13 s390
drwxr-xr-x   6 root root 4096 2004-02-23 11:13 s390x
drwxr-xr-x   8 root root 4096 2004-02-23 11:13 sh
drwxr-xr-x   9 root root 4096 2004-02-23 11:14 sh64
drwxr-xr-x   8 root root 4096 2004-02-23 11:14 sparc
drwxr-xr-x   9 root root 4096 2004-02-23 11:14 sparc64
drwxr-xr-x   9 root root 4096 2004-02-23 11:14 x86_64

Automatica
Tramite il comando make install, si ha la possibilità di spostare in modo automatico i file nella directory /boot:
make install Copia l'immagine del kernel nella posizione precedentemente definita nell'INSTALL_PATH

- CONFIGURAZIONE DEL BOOT LOADER
Configurare il boot loader inserendo la possibilità di eseguire il boot con il nuovo kernel.
Ricordarsi sempre di mantenere un'immagine di un kernel funzionante con la relativa entry nel boot loader come backup per evitare spiacevoli inconvenienti (può capitare di compilare un kernel senza il supporto di driver necessari, che si blocca al boot, per cui è sempre necessario aver la possibilità di bootare con il vecchio, funzionante, kernel).

- REBOOT

Privacy Policy