Compilare un nuovo kernel e installarlo

Molti penseranno che sia difficile compilare il kernel Linux; come in genere pensano che sia difficile compilare: è una cosa tecnica. Ma a compilare non siamo noi, è un programma apposito! E se il pacchetto è ben congeniato, compilare non vuol dire altro che saper impartire un paio di comandi dalla linea di comando.

Normalmente per il software abbiamo la solita trafila

./configure   esegue script di configurazione
make          lancia make, che si occupa di fare l'eseuibile
make install  installa quanto appena compilato

Il programma make legge un apposito file scritto in una sorta di linguaggetto da chi ha creato il programma. Il ./configure controlla, tra le altre cose, che ci sia sul sistema ospite tutto quello che serve per compilarsi.

Per il kernel la procedura è ancora più semplice e altamente automatizzata. Per prima cosa, possiamo voler vedere un po' di parametri da modificare (p.es. make menuconfig per vederli con l'interfaccia ncurses, ovviamente dobbiamo avere gli appositi include)

Fatto ciò potete partire... è solo questione di tempo. Avendo avuto problemi di surriscaldamento, ho preferito, invece di far partire la compilazione per intero, compilare separatamente kernel e moduli per il kernel.

I comandi dati sono stati:

make vmlinux
make modules

Tra il primo e il secondo è passato parecchio tempo, e ancora di più tra il secondo e la sua fine; ma è solo questione di tempo. Alla fine dei due comandi abbiamo il kernel pronto! Che fatica è stata? Nessuna!

A dire il vero per completare il tutto ho dovuto fare anche

make

(Infatti make install mi aveva detto che per poter installare il kernel serviva prima compilarlo... ma come?! probabilmente ci sono alcuni passi ulteriori che selezionando ora vmlinux ora modules non vengono fatti e sono necessari; comunque in questo caso è questione di poco tempo)

Ora, habemus kernel! (E precisamente il 2.6.21.5)

Ok ma ora che ci devo fare? Lo devo installare, ovviamente.

... installazione ...

Anche qui la procedura è semplicissima. Noterete in /lib/modules che ciascun kernel ha la sua cartella per i suoi moduli (il nome del kernel è dato da uname -r).

In /boot del resto la stessa storia (initrd e vmlinux sono postfissi con la versione del kernel); non avremo quindi alcun problema di perdita del precedente kernel, nel caso volessimo tornare indietro.

make install
make modules_install

Fa tutto lui. Oltre a copiare in kernel e i moduli, modifica il link simbolico vmlinuz in modo che punti al nuovo kernel e aggiunge una voce al bootloader (nel mio caso GRUB, quindi non ho dovuto fare niente altro; con LILO bisogna aggiornare qualcosa...)

Ora dobbiamo creare l'immagine iniziale del kernel con i moduli base. Anche in questo caso facilissimo:

mkinitrd -k vmlinuz-2.6.21.5-default -i initrd-2.6.21.5-default

(Forse non serviva specificare la seconda opzione, ma non ho provato).

A questo punto è tutto pronto. Prima di riavviare però ho voluto controllare che /boot/grub/menu.lst mi consentisse ancora di partire con il vecchio kernel... In effetti qui si faceva riferimento ai link simbolici initrd e vmlinuz, per cui ho dovuto mettere il nome del vecchio kernel per esteso —tanto per poter ancora avviare il tutto se qualcosa col nuovo kernel è andato storto.

Fatto ciò ho riavviato.

Riavvio

Durante la fase di boot noto subito dei problemi: degli script di inizializzazione che falliscono. Niente di critico, infatti dopo un po' mi compare il login grafico, olé!

Però il mouse non si muove. Provo il touchpad e funziona. Inserisco username e password ed entro e faccio qualche prova, guardando dmesg: sconnetto e riconnetto il mouse USB. Niente. Muto. Nessun messaggio, né di errore né niente. Come se non sentisse l'USB.

Capperi. Allora faccio un lsmod e noto una mostruosa penuria di moduli caricati. Niente per il suono per esempio (infatti poi mostro l'icona nascosta del mixer in KDE e vedo che c'è una bella × rossa...). E niente per l'USB nemmeno!!

A mano carico tutti i moduli che mi sembrano pertinenti con l'USB; sconnetto e riconnetto... ok questa volta in dmesg compaiono dei messaggi, ma per riavere il mouse (oltre a forzare il server X ad aggiornarsi cambiando terminale con Ctrl+Alt+F1 e poi tornando al terminale grafico con Ctrl+Alt+F7) devo rinominare /dev/input/mouse2 come /dev/input/mouse1 (che è dove X si aspetta di avere il mouse...) Perché è finito invece su mouse2 (essendo mouse1 libero)?

Altro modulo che non è partito e/o non è stato caricato è quello per poter usare i winmodem, cioè slamr (e slusb). Dunque anche niente modem... Perché non è partito? Ovviamente perché non c'è tra i moduli standard del kernel. Senza saper né leggere né scrivere copio /lib/modules/2.6.13-15.15-default/extra nella cartella del nuovo kernel, poi lancio depmod, illudendomi che possa funzionare con modprobe -f.

Illuso! A parte gli avvertimenti (module taints kernel), non può risolvere il simbolo pci_register_driver, che in effetti si trova nell'elenco dei simboli esportati del kernel 13 mentre nel 21 è __pci_register_driver (perché?)

Si potrebbe scavalcare il problema creando un nuovo modulo che sia una sorta di wrapper e che non faccia altro che esportare pci_register_driver e chiamare __pci_register_driver? (Naturalmente potrei anche ricompilare il solo kernel dopo aver modificato drivers/pci/pci-driver.c opportunamente, magari aggiungendo un wrapper direttamente nel kernel ...)

Sarebbe meglio trovare una nuova versione di slamr, driver proprietario... che il cambio di nome dia legato a

What:	USB driver API moves to EXPORT_SYMBOL_GPL
When:	February 2008
Files:	include/linux/usb.h, drivers/usb/core/driver.c
Why:	The USB subsystem has changed a lot over time, and it has been
	possible to create userspace USB drivers using usbfs/libusb/gadgetfs
	that operate as fast as the USB bus allows.  Because of this, the USB
	subsystem will not be allowing closed source kernel drivers to
	register with it, after this grace period is over.  If anyone needs
	any help in converting their closed source drivers over to use the
	userspace filesystems, please contact the
	linux-usb-devel@lists.sourceforge.net mailing list, and the developers
	there will be glad to help you out.

letto in features-removal-schedule.txt? (Cioè che un processo simile sia già avvenuto per il bus PCI?) Tuttavia in pci-core.c l'esportazione del simbolo avviene con EXPORT_SYMBOL, non con EXPORT_SYMBOL_GPL ... Boh.

Risolta la questione del mouse e dell'USB, c'è la questione del suono. Aggiungo dei moduli qua e lì, finché sento il bip della console... ok.

Ancora un altro script di avvio che aveva dato problemi (visto al volo durante la fase di boot) era quello per SuSE Firewall. In particolare non poteva funzionare per via del mancante modulo ip_conntrack. Come mai? Che sia legato a quanto detto in feature-removal-schedule.txt, ovvero

What:	IPv4 only connection tracking/NAT/helpers
When:	2.6.22
Why:	The new layer 3 independant connection tracking replaces the old
	IPv4 only version. After some stabilization of the new code the
	old one will be removed.
Who:	Patrick McHardy <kaber@trash.net>

(però dice che dopo la stabilizzazione del nuovo il vecchio verrà rimosso... Boh. Forse non deriva da qui il problema)

Ricapitolando:

Tutto in automatico... ma all'inizio a mano!

Ora ho dimostrato che le due cose base possono tornare a funzionare (USB e suono). Devo solo automatizzare la loro partenza.

Innanzitutto: perché non vengono caricati? Questo non l'ho capito. Spulciando negli script /etc/init.d per vedere in quali moduli incriminati dovevano essere caricati, ho trovato i moduli per l'USB in kbd!! Strano. Quelli per il suono in alsasound (ok)...

Perché non vengono caricati automaticamente? Cosa c'è di diverso? È una questione di ordine, di velocità del boot, o che?

Penso a una soluzione rapida.

La soluzione rapida è quella di modificare gli script incriminati in init.d in modo che, quando si tratti del kernel 21 (ovvero non del 13), non facciano nulla (skipped, per evitare il messaggio d'errore)

Con questa idea ho quindi aggiunto un codicillo del tipo

if [ `uname -r` != "2.6.13-15.15-default" ]; then
	echo -n "SmartLink is for 2.6.13-15.15! "
	rc_status -s
	rc_exit
fi

In testa agli script, in modo che siano saltati (senza dare errore) nella fase di boot.

Gli script che hanno subito questa sorte sono stati: slmodemd, SuSEfirewall2_init, SuSEfirewal2_setup, splash. Poi ho creato un nuovo script, dal nome kernel21fix (a partire da skeleton), lasciando in pratica tutti i default o quasi. (Il codice completo lo trovate qui)

Questo script aggiunge una marea di moduli per poter usare correttamente USB e suono (ne ho aggiunti altri confrontando quello che dice lsmod se parto con il kernel 13).

Per qualche motivo (ancora da indagare), il mouse USB continua ad andare su mouse2. Ho modificato quindi /etc/X11/xorg.conf:

Section "InputDevice"
  Driver        "mouse"
  Identifier    "Mouse[3]"
  Option        "Buttons" "5"
  Option        "Device" "/dev/input/mouse2"
  Option        "SendCoreEventes" "1"
  Option       "Name" "USB Mouse"
  Option       "Protocol" "explorerps/2"
  Option       "ZAxisMapping" "4 5"
EndSection

Che è del tutto uguale (eccetto Identifier e Device) alla precedente che legge mouse1. Tuttavia un giorno cercherò di capire perché va ora su mouse2 e salta mouse1 (mentre mouse0 è sempre il touchpad, e fin qui tutto ok!)

Per finire con i problemi...

Dopo queste modifiche, attivo tramite il Control Center di SuSE (la mia distro) lo script kernel21fix e riparto.

Tutto apparentemente ok! Ma poi provo a inserire una pennetta USB... In /media non trovo quanto mi aspetto, ma dmesg mi informa che la chiavetta è correttamente su /dev/sda1, tanto che la posso montare a mano. Ma non viene montata automaticamente.

In Konqueror compare in media:/, ma se provo ad aprirla, mi dice che non può montare il device (perché non c'è in fstab ...)

Dopo ulteriori indagini, mi accorgo che tra i moduli mancanti manca quello per subfs che è il filesystem con cui i dispositivi hotplug vengono aggiunti tra i montati (il filesystem reale è poi specificato come opzione) ...

Poco male aggiungiamo a mano il modulo subfs ... Che non c'è!! Il tentativo di aggiungerlo fallisce (come prima già slamr) sempre per qualche simbolo che non può essere risolto... L'unico modulo che mi ispira funzionalità simili è autofs, ma il problema, se fosse lui il sostituto, diventa: come automatizzarlo (mantenendo la compatibilità all'indietro con il kernel precedente in modo che possa partire anche con quello senza dovermi preoccupare di rimodificare qualcosa)?

Anche qui ci sono dei cambiamenti radicali nel kernel? Perché subfs non è supportato (più)? Chi è il sostituto e cosa dovrei cambiare, e soprattutto come cambiare quello che devo cambiare in modo da usare subfs quanto parto con il 13 e quell'altra cosa quando parto con il 21?

Da queste domande deduco che avere un sistema con due kernel diversi non è affatto comodo. Per far funzionare tutto come prima con il nuovo kernel c'è sicuramente un modo (sia per riavere la funzionalità di slamr, sia per l'automounting delle periferiche hotplug, o per qualunque altro problema di cui non mi sono ancora accorto); ma tale modo probabilmente è incompatibile, troppo diverso dal precedente e fa sì che i due kernel non possano essere usati intercambiabilmente con facilità.

O sono deduzioni errate? Lo scoprirò comunque esplorando Internet, appena avrò tempo.

Riflessioni finali

Qualche riflessione finale è d'obbligo: compilare il kernel è stato facilissimo. Anche installarlo. Ma ridare (molte del)le funzionalità precedenti, anche se (per me) non difficilissimo, non è stato affatto liscio. Un utente normale avrebbe abbandonato il nuovo kernel per il vecchio, affindandosi solo agli aggiornamenti della sua distro preferita.

Facendo un test un po' azzardato si arguisce che più spesso che raramente i moduli sono fortemente legati ad una certa versione del kernel. Può essere anche che dalla 13 alla 21 ci sia stata qualche modifica sostanziale che proietta GNU/Linux nel suo futuro, lasciandosi, come giusto, il passato alle spalle.

Questo vuol dire però che aggiornare il kernel (e i moduli) può rendere il sistema non più funzionante come prima. Ovvero, se si vuole aggiornare il kernel (e dunque i moduli), si devono aggiornare tutti, anche quelli non appartenenti al kernel —cioè bisogna reperire i sorgenti (quando disponibili!) e ricompilarli, oppure attendere i comodi di qualche società (per i driver proprietari).

D'accordo che questo non è veramente difficile, però può diventare fastidioso...

Per quanto riguarda un pci_register_driver, perché cambiarne il nome? Possibile che la nuova versione sia così funzionalmente diversa dalla vecchia da rendere necessario impedire l'accesso a tale funzione a chi usa ancora il vecchio nome? Perché non fornire eventualmente un wrapper (sicuramente su Internet c'è una risposta).

Per chiudere veramente c'è anche da dire che tutta questa esigenza di aggiornare il kernel non c'era. Ma se il nuovo è più performante (anche tenuto conto del fatto che l'ho compilato sul mio sistema), magari ha qualche bugfix ed è più stabile... perché non beneficiare di questi vantaggi?

Ma penso che dal punto di vista dell'utente finale, scremati questi problemi, non cambi molto. E allora, proprio considerando questi problemi è forse il caso di tenersi il kernel precedente ...


Home page