Kernel, gestione, configurazione e compilazione

Loris Tissino

10 luglio 2009

Kernel monolitici vs. kernel modulari

Un kernel (nucleo del sistema operativo) può essere compilato come:

La maggior parte degli utenti Linux usa kernel modulari, perché ciò garantisce una maggior flessibilità.

Che kernel sto usando?

Per sapere qual è il kernel in uso si può usare il comando uname -r:

$ uname -r
2.6.27-11-generic

N.B. Da non confondersi con la versione della distribuzione usata:

$ lsb_release -a
Distributor ID: Ubuntu
Description:    Ubuntu 8.10
Release:    8.10
Codename:   intrepid

A partire dal kernel 2.5.48 ci sono state modifiche importanti alla gestione dei moduli (estensione .ko, versioni diverse dei programmi di gestione, ecc.).

Impostazioni dinamiche del kernel

Con il programma sysctl si possono impostare o leggere i valori di configurazione del kernel.

$ sudo sysctl -w kernel.hostname=biegacz
kernel.hostname = biegacz
$ sudo sysctl kernel.hostname
kernel.hostname = biegacz

Il file /etc/sysctl.conf contiene la configurazione letta all'avvio del calcolatore.

Moduli

I moduli disponibili sono nella directory /lib/modules, all'interno di una sottodirectory per la specifica versione di kernel:

$ ls -F /lib/modules/$(uname -r)
build@   madwifi/        modules.ieee1394map  modules.pcimap    net/
extra/   modules.alias   modules.inputmap     modules.seriomap  ubuntu/
initrd/  modules.ccwmap  modules.isapnpmap    modules.symbols   volatile/
kernel/  modules.dep     modules.ofmap        modules.usbmap

Nella maggior parte dei casi, i moduli vengono caricati automaticamente quando necessario. In casi di particolari necessità, può essere utile saper elencare, caricare o rimuovere moduli dal kernel.

Elenco dei moduli caricati

L'elenco dei moduli caricati si ottiene con il comando lsmod (oppure, con output diverso, visualizzando il file /proc/modules).

$ lsmod | head -10
Module                  Size  Used by
vesafb                  8964  0 
wlan_tkip              13568  0 
aes_i586               33536  0 
geode_aes               7176  0 
blkcipher               8324  1 geode_aes
aes_generic            27712  0 
wlan_ccmp               9600  0 
af_packet              23812  0 
binfmt_misc            12808  1 

Caricamento di un modulo

I moduli possono essere caricati direttamente con insmod, che però non risolve automaticamente le dipendenze:

$ cd /lib/modules/`uname -r`
$ find . -iname msdos
./kernel/fs/msdos

$ sudo insmod ./kernel/fs/msdos/msdos.ko 
insmod: error inserting './kernel/fs/msdos/msdos.ko': -1 Unknown symbol in module

$ sudo insmod ./kernel/fs/fat/fat.ko 
$ sudo insmod ./kernel/fs/msdos/msdos.ko 

(Teoricamente dovrebbe essere possibile inserire i moduli usando solo il loro nome, senza il percorso completo)

Rimozione di un modulo

I moduli possono essere rimossi con rmmod, che però fallisce se ci sono dipendenze:

$ sudo rmmod fat
ERROR: Module fat is in use by msdos

$ sudo rmmod msdos
$ sudo rmmod fat

Informazioni su un modulo

Si possono ottenere informazioni su un modulo (ad esempio le sue dipendenze) con modinfo:

$ modinfo msdos
filename:       /lib/modules/2.6.24-16-generic/kernel/fs/msdos/msdos.ko
description:    MS-DOS filesystem support
author:         Werner Almesberger
license:        GPL
srcversion:     4BF2299125E22266BA734C0
depends:        fat
vermagic:       2.6.24-16-generic SMP mod_unload 586 

Installazione e rimozione semplificate

Con il comando modprobe si possono installare e rimuovere i moduli con il riconoscimento automatico delle dipendenze:

$ sudo modprobe -v msdos
insmod /lib/modules/2.6.24-16-generic/kernel/fs/fat/fat.ko 
insmod /lib/modules/2.6.24-16-generic/kernel/fs/msdos/msdos.ko 
$ sudo modprobe -rv msdos
rmmod /lib/modules/2.6.24-16-generic/kernel/fs/msdos/msdos.ko
rmmod /lib/modules/2.6.24-16-generic/kernel/fs/fat/fat.ko

Tipi e formati di kernel

Il kernel di Linux è un file eseguibile risultante dalla compilazione dei sorgenti del kernel stesso.

Bisogna distinguere:

I sorgenti del kernel

Il codice sorgente del kernel linux è disponibile nei Linux Kernel Archives.

Sono molte le patch rese disponibili da programmatori e aziende di tutto il mondo. Il kernel ufficiale, senza queste patch, è detto kernel vanilla.

I numeri di versione hanno la forma major.minor.patchlevel.

Un valore pari per minor indica un kernel indicato come stabile, un valore dispari un kernel di sviluppo (non c'è ancora un kernel 2.7).

Verifica della firma digitale

I file disponibili su www.kernel.org sono firmati digitalmente con gpg da ftpadmin@kernel.org.

Dopo aver scaricato un file, è consigliabile verificarne la firma digitale:

$ wget -c http://www.eu.kernel.org/pub/linux/kernel/v2.6/patch-2.6.25.gz
[snip]
16:09:32 (65.55 KB/s) - "patch-2.6.25.gz" salvato [11759164/11759164]

$ wget -c http://www.eu.kernel.org/pub/linux/kernel/v2.6/patch-2.6.25.gz.sign
[snip]
16:09:52 (7.88 MB/s) - "patch-2.6.25.gz.sign" salvato [248/248]

$ gpg --verify patch-2.6.25.gz.sign patch-2.6.25.gz   # dopo aver importato la chiave pubblica...
gpg: Firma fatta da gio 17 apr 2008 05:23:09 CEST usando DSA ID chiave 517D0F0E
gpg: Good signature from "Linux Kernel Archives Verification Key <ftpadmin@kernel.org>"

Le fasi della compilazione del kernel

Per ricompilare il kernel, si deve procedere in questo modo:

  1. scaricare gli strumenti di lavoro (compilatore, linker ecc.)
  2. scaricare i sorgenti del kernel (della propria distribuzione o vanilla) e scompattarla
  3. scaricare eventuali patch che si desiderano utilizzare
  4. applicare le patch
  5. fare la configurazione (vedi oltre)
  6. compilare (approfondimento successivo)
  7. installare e testare (approfondimento successivo)

Configurazione del kernel (1)

La configurazione avviene tramite appositi strumenti (alternativi tra loro) che aiutano a creare il file .config.

Configurazione del kernel (2)

Per ogni caratteristica distintiva (feature) bisogna indicare se si desidera che essa:

Può essere utile:

Compilazione

La compilazione attraversa tradizionalmente le seguenti fasi:

  1. make dep (genera le dipendenze)
  2. make clean (elimina file creati provvisoriamente in compilazioni precedenti)
  3. make bzImage (genera il kernel compresso e avviabile)
  4. make modules (genera i moduli)
  5. make modules_install (installa i moduli nella directory /lib/modules/...)

Se tutto è andato a buon fine, si deve ancora:

  1. copiare il file bzImage nella directory /boot/ (con un nome tipo vmlinuz-versionex
  2. aggiornare la configurazione del bootloader (lilo o grub)
  3. riavviare la macchina scegliendo il nuovo kernel, testandone le funzionalità

Compilazione Debian-way e Fedora-way

Compilazione ed installazione sono resi più semplici da appositi programmi che permettono di creare normali pacchetti deb o rpm da installare e rimuovere nella maniera consueta.

$ make-kpkg clean  
$ fakeroot make-kpkg --revision ~0.01 --append-to-version -versione01 hernel_image kernel_headers modules_image
$ cd ..
$ sudo dpkg -i linux-headers-*.deb  
$ sudo dpkg -i linux-image-*.deb  
$ sudo dpkg -i modules-image-*.deb 

Al termine, ci si troverà un nuovo kernel installato e selezionabile dal menù di grub, e che potrà essere disinstallato come qualsiasi altro pacchetto.

$ dpkg --list | grep 'linux.*versione0'
ii  linux-headers-2.6.24.3-versione0  ~0.00   Header files related to Linux kernel, specifically,
ii  linux-image-2.6.24.3-versione0    ~0.00   Linux kernel binary image for version 2.6.24.3-versione0

Qualcosa di analogo si può fare con Fedora.

Initrd e Initramfs

Nella directory /boot trovano normalmente posto anche i file initrd (initial ram disks), filesystem minimali completi necessari per un primo avvio della macchina (che può così avvenire anche con un kernel in cui il supporto per particolari filesystem sia compilato come modulo). Questi file sono normalmente (dal kernel 2.6) in formato cpio compresso con gzip e sfruttano il filesystem initramfs.

$ file /boot/initrd.img-2.6.24-16-generic
/boot/initrd.img-2.6.24-16-generic: gzip compressed data, from Unix, last modified: Wed Apr 30 22:40:44 2008
$ zcat /boot/initrd.img-2.6.24-16-generic | cpio --extract 
40110 blocks
$ ls -F
bin/  conf/  etc/  init*  lib/  modules/  sbin/  scripts/  usr/  var/