Compilazione del kernel Linux: come e perchè (con una breve introduzione)

by Stefano Belli on

Abbiamo già affrontato questo argomento in passato, in questo articolo, in quest’altro l’argomento verrà spiegato in modo più approfondito.

Che cos’è il kernel?
Come detto la scorsa volta, il kernel è un software che gestisce le risorse hardware, i processi di un sistema operativo, ed è il primo programma ad essere lanciato dopo il bootloader e la ramdisk; si occupa di avviare il sistema di init, i servizi e si occupa inoltre di caricare i driver.
Il kernel può essere di diverso tipo: microkernel(Mach), kernel ibrido (Sistemi MS-DOS), monolitico(BSD, Linux), ecc… Ognuno può essere utilizzato per diversi scopi. Per maggiori info… Google!
E’ corretto definire Linux un sistema operativo(OS/SO)?
No, e NO!
Linux è un kernel, che è parte integrante del sistema operativo, uno dei software del sistema operativo, infatti, Linux è parte integrante di GNU, creato da Richard Stallman.
E’ corretto dire che GNU è un sistema operativo, e che si integra con vari kernel, il più diffuso è Linux (GNU/Linux), ma può integrarsi anche con altri kernel come Hurd, kFreeBSD, Darwin.
GNU è un sistema operativo Unix-like (GNU’s Not Unix) ed è composto da vari software:

  • Editor di testo: GNU Emacs
  • Fotoritocco: GIMP
  • Desktop Environment, Window Manager: GNOME
  • Display Manager: GDM
  • Visualizzatore di foto, riproduttore musicale: gThumb, Rhythmbox
  • Un kernel: nel nostro caso Linux
  • Una shell: Bash, zsh, sh ecc…
  • Sistema di init: systemd, upstart …

Quindi sarebbe corretto dire che Debian (o Fedora, Ubuntu, RedHat, Arch Linux, Slackware, ecc…) sono sistemi operativi basati su sistema operativi GNU con kernel Linux, anche se ci sono distribuzioni che utilizzano kernel Hurd come il progetto Debian GNU/HURD.
Dopo questa spiegazione, passiamo al secondo punto

Linux da chi è sviluppato, e come?
Linux è stato sviluppato da Linus Torvalds, verso la fine degli anni 80 (se non ricordo male), e prende il nome proprio dal suo main developer. Nel 1991-1992 il sistema operativo GNU era quasi pronto, mancava un componente: il kernel. Ecco che si presenta Linux, che venne rapidamente integrato con GNU.
Ecco che nasce GNU/Linux (la fusione di GNU e Linux), Linux comincia sempre di più ad attirare attenzione grazie anche a RedHat (RHEL), lo sviluppo continua in maniera esponenziale grazie alle mailing list da vari sviluppatori in tutto il mondo, hobbysti e dipendenti di grandi società (tutt’ora molti sviluppatori di RHEL, Debian, Arch contribuiscono allo sviluppo di Linux). GNU/Linux si diffuse in ambiente Server grazie alla sua stabilità e reattività, in ambiente desktop, purtroppo, ancora “regna” Windows, ma perde piano piano terreno, grazie alla diffusione di distribuzioni come Ubuntu o Linux Mint

In che linguaggio di programmazione è sviluppato Linux?
Linux è sviluppato in C, linguaggio derivato dal B e sviluppato da Dennis Ritchie, un fisico e matematico che ha anche sviluppato UNIX, insieme a Ken Thompson. Senza di loro BSD, GNU, e i vari sistemi operativi UNIX (tra i quali MacOS (basato a sua volta su FreeBSD) non esisterebbero, probabilmente addirittura Windows non esisterebbe (è sviluppato in C).
Dennis Ritchie è morto a Ottobre del 2011, poco dopo la morte di Steve Jobs, nonostante questo NON E’ RICORDATO COME STEVE JOBS, CHE AL CONTRARIO È RICORDATO COME UN RIVOLUZIONARIO. Dennis deve essere ricordato quanto Steve, senza di lui, mi dispiace Apple fans, ma ora non avreste avuto i vostri iPhones, iPads, iPods, iMac, MacBook, etc…, adesso, mentre scrivo non sò quante persone leggeranno il mio articolo ma spero che lo leggeranno il più possibile, non per ottenere più visibilità, ma per invitarle a conoscere chi veramente ha reso possibile

  1. GNU
  2. Linux
  3. BSD
  4. Windows
  5. MacOS
  6. Android
  7. iOS

Credo che basti.

Oggi, come interagiscono i vari sviluppatori?
Mai sentito parlare di Git?
Git è un VCS, sviluppato da Linus Torvalds (utilizzato da Google, Facebook, AOSP, CyanogenMod e molti altri progetti open source) ovvero un Version Control System (Sistema di controllo versione), permette di creare un repository, diciamo un contenitore, che “contiene” i pezzi del kernel Linux. Contiene il codice sorgente del kernel Linux (Distribuito sotto licenza GNU General Public Licence [GPL]), che utilizzeremo per compilare il kernel, appunto.
Più utenti in tutto il mondo, scaricano il codice sorgente, effettuano le modifiche al codice del kernel (diviso in vari headers e source in C) e poi “pushano” le modifiche al repository Git di Linux commentando e motivando le modifiche al codice sorgente (il fix di un bug ad esempio).
Tuttavia è possibile ottenere il codice sorgente di Linux direttamente scaricando una tarball da qui
Esistono numerosi siti di git-hosting: GitHub, BitBucket e altri..
Oltre a Git esistono altri VCS come Mercurial.

Utilizzeremo…?

  1. make
  2. mkinitcpio
  3. grub-mkconfig o update-grub

Perchè compilare un proprio kernel?
Se si conosce a fondo il proprio hardware, è buona norma compilare il kernel da sé, perché il kernel che viene fornito con la distribuzione carica moduli, firmware, drivers che a voi molto probabilmente non servono. Driver inutili, inoltre, avete la libertà di aggiornare il kernel quando volete e come volete, specialmente in distribuzioni come Debian, piano piano ci farete l’abitudine

Curiosità: qui potete leggere la tesi di laurea di Linus Torvalds – Linux: a portable operating system

Dove troviamo il codice sorgente di Linux?
Lo trovate proprio qui, vi consiglio di scaricare l’ultima versione stabile, se siete invece più curiosi, scaricate la 4.0-rcX (quella che io utilizzo ), scaricate la tarball (tar.xz).

Quanto pesa il codice sorgente (compresso), come capisco la versione che sto scaricando
Il codice sorgente di un kernel pesa più o meno 70 MB in una tarball (compressa).
Prendiamo in esame una versione di Linux e vediamo come leggere la versione, il che, è molto semplice

linux-4.0-rc7.tar.xz

-linux=default
-4.0-rc7=x.y-rcZ: Versione maggiore.release minore-releaseCandidate(NumeroDellaRC)
-*3.19.3=x.y.z: Versione maggiore.release minore.release ancora minore
-Versione maggiore=la ‘serie’ del kernel – ovvero: 4, 3, 2, 1, 0 : aggiunta di funzioni notevoli, aggiunta di molti drivers, miglioramento delle prestazioni.
-release minore=Un aggiornamento della Versione maggiore, si aggiungono di solito supporto per nuovi hardware, e funzioni aggiuntive di non molto rilievo.
-releaseCandidate=una ‘beta’ del kernel, versione instabile, probabilità di trovare bugs notevole.
-release ancora minore=bugfix di un kernel stabile
-tar.*=algoritmo di compressione del sorgente

longterm, stable, mainline
-longterm: kernel con supporto aggiuntivo, vecchi, ma con probabilità minima di instabilità e bugs
-stable: kernel “corrente” pronto per essere utilizzato e testato
-mainline: ultima versione del kernel

Mai sentito parlare di modprobe?

modprobe

è un programma che consente di caricare, rimuovere, mostrare le dipendenze di un modulo del kernel, la cosa bella è che consente di “smontare” il kernel a proprio piacimento in tempo reale.
Ad esempio, voglio caricare il modulo che contiene il blocco di codice che permette alla mia webcam di funzionare (uvcvideo, Acer CrystalEye Webcam), eseguo

# modprobe uvcvideo

se per qualsiasi ragione voglio smettere di farla funzionare

# modprobe -r uvcvideo

che rimove il modulo dal kernel

Oppure voglio vedere i moduli necessari al caricamento del modulo della mia webcam:

# modprobe -D uvcvideo

per tutte le opzioni che modprobe consente di utilizzare è possibile utilizzare

$ modprobe -h

DKMS – Dynamic Kernel Module Support e linux-headers

dkms

e

linux-headers

sono due software che permettono la compilazione di moduli/driver che il kernel non ha nel suo codice sorgente, un esempio comune sono i driver di VirtualBox per l’emulazione delle macchine virtuali (vboxdrv).
Di solito non sono inclusi nelle distribuzioni ed è sufficiente scaricarli dal proprio package manager

pacchetto:

dkms

pacchetto:

linux-headers-$(uname -r)

Utility make
Ci serviremo di GNU Make per compilare il kernel e i suoi drivers, è un tool che attraverso delle istruzioni, contenute in un file chiamato “Makefile” ci consente di compilare un programma da sorgente, è una versione moderna della vecchia make, e ne esistono varie, come BSD Make (bmake) o Microsoft Make (nmake)


Passiamo ora alla compilazione

Estraiamo i files e navighiamo nella cartella di destinazione
Estraiamo la tarball scaricata

 tar -xf <pacchetto.tar.*>

e navighiamo con cd (change directory)

 cd

Preparazione dell’ambiente e pulizia files inutili
All’interno della cartella eseguiamo

$ make mrproper

Scriviamo un file di configurazione
Il kernel ha bisogno di sapere quali moduli/drivers abilitare di default, quale modularizzare, quali non caricare(ignorare) etc…
Per fare questo è possibile utilizzare 3 strumenti
-make menuconfig (Programma a interfaccia semi-grafica ncurses) [Consigliato]
-make gconfig (Programma a interfaccia grafica Gtk)
-make xconfig (Programma a interfaccia grafica Qt)
Io consiglio menuconfig, in quanto non crasha ed è molto più veloce rispetto agli altri due, inoltre in gconfig si è spesso soggetti a crash improvvisi che costringono l’utente a riaprire un nuovo config file.
In menuconfig:
-Tasto : modularizza un modulo/driver ( < > )
-Tasto : abilita un modulo/driver ( [ ] )
-Tasro : disabilita un modulo/driver ( < > ; [ ] )

se vogliamo utilizzare il config del nostro kernel dobbiamo copiare

/proc/config.gz

nella directory di un livello sopra a quella attuale (..), scompattare l’archivio cambiare il possessore del file e copiare il file nella subdirectory del kernel

# cp /proc/config.gz ~
# chown  config.gz
# exit
$ gzip -d config.gz
$ cp .config

*Attenzione a deselezionare 64-bit kernel type se il vostro OS non è su architettura a 64 bit

Avvio della compilazione
Per avviare la compilazione del kernel è necessario eseguire semplicemente make, che leggerà il Makefile, e il .config per configurare il kernel.

make

Avvia la compilazione sfruttando un solo core della CPU

make -j3

Avvia la compilazione sfruttando due core della CPU

make -jX

Avvia la compilazione sfruttando X core della CPU

Normalmente, a seconda dei moduli, con 2 core impiega 15 minuti (moduli necessari, configurazione personalizzata)

Installazione headers e moduli nella folder /lib/modules
Eseguiamo i seguenti comandi per installare i moduli (*.ko) e gli headers del kernel in /lib/modules/X.Y.Z

# make modules_install
# make headers_install

Copia del kernel e di System.map in /boot
E’ necessario copiare il kernel in /boot e System.map, dove sono contenute le ramdisk, le immagini dei kernels, e la configurazione del bootloader GRUB.
Copiare il kernel

# cp arch/x86/bzImage /boot/vmlinuz-kernel.ver.sion

Copiare System.map

# cp System.map /boot/System.map

Generazione immagine della ramdisk
E’ generalmente utilizzato update-initramfs in sistemi Debian e anche RedHat, mkinitcpio per sistemi basati su Arch Linux.

# update-initramfs -k <versione_del_kernel_in_/lib/modules> -c
# mkinitcpio -k <versione_del_kernel_in_/lib/modules> -g /boot/initramfs-<versione_del_kernel_in_/lib/modules> -c /etc/mkinitcpio.conf

Aggiornamento configurazione GRUB
Per aggiornare il bootloader GRUB:

# grub-mkconfig -o /boot/grub/grub.cfg

oppure

# update-grub

.

Adesso basterà riavviare e potrete utilizzare il vostro kernel fatto in casa!

Potete eseguire le stesse operazioni utilizzando LinuxCleaner

Sto anche sviluppando una versione a interfaccia grafica (GTK+), sicuramente più gradevole e con un semplice script d’installazione. Qui il codice sorgente.

Il post Compilazione del kernel Linux: come e perchè (con una breve introduzione) è stato pubblicato su InTheBit - Il Blog sulla Tecnologia che alimenta le tue passioni!.

Leggi il contenuto originale su InTheBit - Il Blog sulla Tecnologia che alimenta le tue passioni! » Linux

Written by: Stefano Belli