non posso caricare immaggini
mario
Linux - Compilare Il Kernel
 Di  Mario Spanò , June 18, 2020, 6:30 p.m.

Non sono in alcun modo responsabile per eventuali cattivi funzionamenti del vostro sistema . Questo tutorial usa una procedura generica che potrebbe non funzionare su alcune distribuzioni Linux. La compilazione del kernel è una procedura che può facilmente rendere un sistema inutilizzabile ,se non si sa quello che si sta facendo. Un buon consiglio affinchè ciò non accada , è di usare il kernel che compileremo come secondo kernel , e di non cancellare , il kernel della distribuzione.

Installiamo Le Dipendenze

La maggior parte dei pacchetti elencati nella figura 0.a dovrebbero essere già installati sulle distribuzioni Linux più usate . i primi 5 della lista sono fondamentali , quindi assicuratevi che siano installati . Per installarli :

Su Debian/Ubuntu e derivate :

mario@androgenic:~/Scaricati/linux-5.6.10 #apt install build-essential libncurses5-dev


Su Fedora e derivate :

mario@androgenic:~/Scaricati/linux-5.6.10 #yum groupinstall ‘Development Tools’



0.a
Programma Versione Minima Comando
GNU C 3.2 gcc –version
GNU make 3.80 make –version
binutils 2.12 ld -v
util-linux 2.10o fdformat –version
module-init-tools 0.9.10 depmod -V
e2fsprogs 1.41.4 e2fsck -V
jfsutils 1.1.3 fsck.jfs -V
reiserfsprogs 3.6.3 reiserfsck -V
xfsprogs 2.6.0 xfs_db -V
squashfs-tools 4.0 mksquashfs -version
btrfs-progs 0.18 btrfsck
pcmciautils 004 pccardctl -V
quota-tools 3.09 quota -V
PPP 2.4.0 pppd –version
isdn4k-utils 3.1pre1 isdnctrl 2>&1|grep version
nfs-utils 1.0.5 showmount –version
procps 3.2.0 ps –version
oprofile 0.9 oprofiled –version
udev 081 udevd –version
grub 0.93 grub –version || grub-install –version
mcelog 0.6 mcelog –version
iptables 1.4.2 iptables -V
openssl & libcrypto 1.0.0 openssl version
bc 1.06.95 bc –version
Sphinx 1.2 sphinx-build –version

Alcuni pensano , che in informatica , compilare significhi : selezionare un opzione piuttosto che un altra da una lista di opzioni , altri che significhi scrivere(compilare) codice di programmazione . Compilare , in informatica , identifica il processo svolto appunto da un compilatore di codice (cc, gcc, javac ,ecc..) che consiste nella conversione di un listato di codice informatico comprensibile ad un uomo ( normale codice di programmazione ) in una sequenza di: 0 1 ,comprensibili per un computer . Quindi il Kernel che ora scaricheremo è codice comprensibile ad un uomo , ad esempio : function scaricaKernel(link,os,version,) { if (url.validate==True) { ..... } } che noi compileremo in codice comprensibile ad una macchina (linguaggio macchina) : 0 1 0 0 1 attraverso l' uso di un compilatore C , C ++ , con l ' ausilio dello strumento MAKE. può sembrare compilcato , ma ricordo che un argomento è complicato finchè non lo si conosce , dal momento che lo si è appreso diventa semplice.



Download Del Kernel

Quindi dopo aver installato le dipendenze per la buona riuscita della compilazione , scarichiamo il kernel qui. una versione del kernel uguale a quella in uso dal sistema è la scelta ottimale perchè useremo localmodconfig per scrivere il file .config nella cartella del kernel . Il file scaricato dovrebbe essere compresso, quindi:

decomprimiamolo cosi :

$ unxz linux-a.x.by.tar.xz







estraiamo l' archivio tar :

$ tar xvf linux-a.x.by.tar

A questo punto abbiamo la cartella : linux-x.y.ab scompattata . Il file di configurazione del Kernel si chiama .config si trova nella cartella principale del kernel ed è nascosto ( tutti i file preceduti da un punto sono files nascosti ) potrebbe essere configurato con qualsiasi editor di testi , ma è meglio usare le utilità offerte dal gestore pacchetti , come quelle visulizzabili con i comandi : make xconfig , make nconfig , make gconfig ecc.. la figura 8a mostra l' interfaccia di configurazione di un file .config attraverso l' uso del comando make nconfig ogni parametro del file di configurazione .config può ammettere l' inserimento di un valore , ad esempio il parametro per lo standby di una scheda , oppure le opzioni di scelta per il driver della CPU , lo scheduling , il tipo di preemption (la modalità di assegnamento risorse), che può essere per server o per desktop. Oppure può ammettere al massimo tre risposte possibili : <*> , < > , <m> come si può vedere sempre nella figura 1.a.

figura 1.a

<*> questa scelta applicata ad esempio ad un driver , fa si che esso sia caricato nel kernel, ma non dal filesystem , non essendo presente sul filesystem e cioè l' aria di memoria su cui un amministratore può effettuare modifiche , non è possibile interagire con esso. quindi l' amministratore una volta scelto di attivare l' opzione , questa sarà per sempre attiva senza possibilità di modificarla in seguito , all' avvio del sistema per esempio come avviene quando si sceglie l 'opzione <m> .

<m> compila la parte del kernel a cui si riferisce come modulo (m) , appunto , e lo mette sul filesystem ,il vantagggio in questo caso (m) è che si può scegliere all' avvio del sistema se caricare il modulo oppure no . I kernel precompilati delle distribuzioni , usano compilare le opzioni soprattutto come modulo , in quanto non possono sapere a priori , quale sia l 'hardware su cui verrà installato il kernel , così preferiscono riservarsi la scelta "carico/non carico" dopo aver letto ( con un software ) quale sia l' hardware su cui sta girando il Kernel . Alcuni sistemi operativi come Debian , offrono sia la possibilità di selezionare tutti i drivers presenti sul kernel , selezionandoli tutti , sia la possibilità di selezionare solo quelli realmente necessari al sistema , specificando però che esiste il rischio , che alcuni moduli necessari non vengano caricati . In più , attivando un driver come modulo , si da all' utente la possibilità di abilitare e disabilitare un opzione o un driver al bisogno ,

< > sta per no , e semplicemente non carica l ' opzione su cui è applicata la scelta

Ci si potrebbe chiedere : ma non è meglio selezionare tutte le opzioni come modulo (m) , visto che si ha un livello d' interazione più elevato ? La risposta è : purtroppo non è possibile ! consideriamo i driver per i canali SATA del hard disk , perchè non è possibile selezionare i driver dell' hard disk come modulo (m) ? risposta : il sistema per caricare un modulo deve poter accedere al hard disk ! ma come fa ad accedere all' hard disk se ancora non ha letto i drivers(moduli) per l' hard disk ??! la soluzione a questo problema esiste ed essa è rappresentata dal file initrd l' immagine giù e presa da Wikipedia :

- Entriamo nella cartella linux e azzeriamo le dipendenze con il comando mrproper

Il comando mrproper serve a pulire la cartella in cui ci troviamo da precedenti compilazioni , è una sorta di make clean approfondito. Più specificamente mrproper rimuove i file generati , come detto prima , in precedenti compilazioni , i files di backup , e perfino il file .config che è il file in cui è memorizzata la configurazione del kernel che verrà compilato , quindi se non volete cancellare un file .config fate un backup prima di eseguire mrproper . basta rinominare il file .config in config.bak e mrproper non lo cancellerà più.

Configurazione Del Kernel

l' immagine 0b sotto , è presa dal sito kernel.org e mostra le principali utilità per configurare il kernel . Personalmente preferisco usare 'nconfig' , ma è questione di preferenze e librerie di sistema , chi usa gnome come dm , sarà piu propenso ad usare gconfig , chi usa kde 'xconfig' , ma certo nulla vieta di fare il contrario.


se scegliete di usare 'nconfig' potrebbe essere necessario installare : bison , flex , libncurses5-dev .


- quindi i primi cinque comandi della finestra sopra :


make nconfig

make xconfig

make gconfig

make menuconfig

make config


aprono un interfaccia testuale per la configurazione del kernel. La finestra sotto mostra ad esempio la finestra che si apre sul mio PC con il comando make nconfig

8a

Sfortunatamente non è per nulla semplice capire quali sono veramente tutte le opzioni che servono al nostro sistema , il sistema operativo quasi sempre riesce a capire quali moduli servono, e li carica, tuttavia non di rado , occorre apportare modifiche al kernel se si vuole avere un sistema performante , ad esempio le distribuzioni impostano il driver del processore , sul loro kernel precompilato sempre su "Generic" . La CPU deve essere immediatamente operante , non è possibile selezionare il driver della CPU come modulo , la CPU non si può permettere di attendere un driver funzionante dopo l' avvio del sistema , come si potrebbe permettere una scheda audio , o un driver per il sensore delle scoreggie , un sistema per avviarsi deve avere un processore ! quindi anche se possibile , per alcuni componenti hardware , non ha molto senso avere moduli per drivers , devono essere subito operativi , a questi componenti non si può delegare l' immediata operatività , e quando lo si può fare è perchè c'è un altro driver già funzionante che lavora a monte , come succede per una scheda video , posso attivarne i drivers come moduli solo perchè al boot il sistema ha dei drivers che se pur minimali , garantiscono il corretto funzionamento della scheda . Quindi deselezionare il driver generic della cpu e selezionare il driver giusto (amd , intel , via ecc...) poi come numero di processori l' opzione giusta è (numero core) + 1 , quindi se ho un octacore seleziono : 9 . Il modo migliore per scrivere un file .config funzionale , penso che sia quello di usare lsmod con make localmodconfig per poi rifinere la configurazione manualmente . lsmod serve a visualizzare i moduli del kernel caricati dal sistema operativo che sta girando. Questo comando se usato con make ci copia la configurazione attuale del kernel in uso nel file .config del kernel che ci apprestiamo a compilare . C' è da dire che molte distribuzioni linux applicano questo strumento automaticamente , scrivendo per noi il file .config , ma questo avviene solo se installo un kernel dal gestore dei pacchetti . Se prendo il kernel dal sito "kernel.org" ovviamente devo operare da solo. Di seguito la procedura per riscrivere il file .config con "make lsmod":


Creiamo La Lista Dei Moduli

- creiamo il file mod contenente l' output del comando lsmod:

$ sudo lsmod > mod

il comando della riga precedente redirige , per mezzo del simbolo :> , il risultato del comando : lsmod appunto , che serve a visualizzare la lista dei moduli del kernel caricati dal sistema operativo , in un file che abbiamo chiamato mod , ma avremo potuto usare qualsiasi altro nome ovviamente .


- Controlliamo che sia stato creato il file : mod:

$ cat mod

- Se il file non è vuoto si può procedere a scrivere la configurazione in .config così:

Attiviamo I Moduli In .config



$ make LSMOD=mod localmodconfig


localmodoconfig legge i moduli nel file mod che abbiamo creato precedentemente , e configura il kernel allo stesso modo , attraverso la scrittura del file .configal cui interno saranno attivati i stessi moduli del kernel attualmente in uso . Questa procedura riduce al minimo il rischio di ritrovarsi con una configurazione inconsistente e quindi con un sistema che non parte (cosa che al sottoscritto è capitata un migliaio di volte) . Se nel nuovo kernel ci sono moduli da attivare/disattivare non ancora presenti nella lista del file mod , lo script localmodconfig ci chiederà dal terminale se attivare o meno il nuovo modulo . chi volesse cimentarsi in una configurazione manuale , puo eseguire l' utilità di configurazione make nconfig come fatto prima. Se volete compilare il kernel affinchè si avii senza initrd dovete impostare tutti i drivers che servono a far partire il sistema in modalità "built in" cioè non come moduli e quindi selezionando <y> nella configurazione , se invece non vi sentite sicuri e non volete rischiare di ritrovarvi con un sistema che non parte( rischio molto elevato anche se lo si usa ) , il consiglio è quello di usarlo . vi risparmia parecchi grattacapi . Dopo che avremo compilato il kernel , mostrerò come generare un immagine initrd.




Prima Di Compilare



per compilare lanciate make dalla cartella linux-x.y.ab
se avete un processore con più di due core ,e volete compilare più velocemente , usate il parametro -j che prende come parametro il numero di processi consentito . Se non indicato , ne permette un numero infinito , tuttavia nelle distro in genere al parametro MAKEOPTS viene assegnato un valore = -j2 , che è perfetto per un monocore , che usa un processore fisico più uno virtuale , ad esempio io che possiedo un octacore su una distro Gentoo linux nel file make.conf imposto la variabile MAKEOPTS="-j9" tuttavia make.conf , nelle altre distro non mi risulta che esista , per questi sistemi bisogna esportare la variabile d' ambiente concurrency_level=-j(numeroprocessori + 1) nel file .bashrc o /etc/profile ecc.. . Anche in Debian/Ubuntu va impostata la variabile concurrency_level=x , oppure è possibile usare il parametro -j in make da riga di comando , soluzione che funziona ovunque . Ho sentito parecchi pareri discordanti sull' utilità di usare la flag -j , ma alla fine il dato inconfutabile è uno solo , è evidente che se compilo con il parametro -j9 su una cpu octacore finisco di compilare prima di quanto riesca a fare senza -j9, e il motivo è evidente anche osservando i grafici del carico della cpu , che monitorano tutte e 8 cpu . Le cpu durante la compilazione sono tutte e 8 al 100% di carico , quindi è ovvio perchè il processo di compilazione duri meno . D' altronde è anche vero che se impegno tutte e 8 cpu al 100% poi non ho risorse per fare altro che compilare .


Compilazione

Compiliamo con :
mario@androgenic:~/Scaricati/linux-5.6.10$ make


Oppure per velocizzare il processo , esempio Per un Octacore :
mario@androgenic:~/Scaricati/linux-5.6.10$ make -j9


Per un QuadCore :
mario@androgenic:~/Scaricati/linux-5.6.10$ make -j5





Installiamo I Moduli

installiamo i moduli con :
mario@androgenic:~/Scaricati/linux-5.6.10$sudo make modules_install


Installiamo il Kernel In Boot ...

Assicuratevi che la partizione boot sia montata , perchè il comando make install che useremo dovrà scrivere dei files al suo interno. Se volete usare initrd , installate il pacchetto initramfs-tools necessario per la sua creazione. installiamo il kernel e copiamo alcuni file nella cartella boot con :

mario@androgenic:~/Scaricati/linux-5.6.10$ sudo make install

il comando make install tra l' altro copia il kernel dalla cartella di compilazione nella directory boot e generà initramfs o initrd , come si può vedere nell' imaggine qui sotto :




Se avete compilato il kernel con il file .config della distribuzione linux che usate, dovrete creare il file initrd affinchè possano essere caricati i moduli per far avviare il sistema , per il fatto che praticamente tutte le distribuzioni Linux , compilano il kernel della propria distro appunto , appositamente per il suo uso con initrd. Di seguito mostrerò come crearlo Nel caso non ci siate riusciti prima.


Initrd o Initramfs

Il file Initrd o il più recente initramfs contiene essenzialmente i moduli (drivers) che servono ad un pc per avviarsi . Initrd emula un filesystem di root che può essere montato sulla ram , su una periferica di loopback , su un floppy . il sistema dopo aver eseguito initrd , libera la memoria e monta la partizione vera di root del sistema operativo.




Creazione di initramfs

Per creare initrd eseguite con sudo o come amministratore :
# mkinitramfs 5.6.10 -o initramfs-5.6.10.img


il primo parametro e cioè 5.6.10 è la versione del kernel che abbiamo compilato e su cui vogliamo creare l' initrd. la flag -o sta per output e definisce il nome del file creato in questo caso initramfs-5.6.10.img fate attenzione a non usare nomi strani nel parametro -o perchè c' è il rischio che gli script come : grub-mkconfig non trovino il file quando dovranno generare il file di configurazione/avvio per il bootloader : grub.cfg ecc... . Se volete vedere tutte le versioni di kernel disponibili , queste sono elencate in  /lib/modules Se volete sapere la versione del kernel in uso dal sistema eseguite :

$ echo $(uname -r)

Configurare Grub Per L' Avvio

Questo passo dovrebbe non essere necessario perchè il comando make install lo svolge automaticamente . Sui sistemi Debian/Ubuntu eseguire :

update-grub

la procedura standard che va bene su tutti i sistemi linux è :
come amministratore da console :

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

Riavviate il pc per provare il kernel .