Ricompilare il kernel Linux è una tecnica che si pratica per ottenere dei risultati specifici con il proprio sistema operativo.
Linux, come tutto il progetto GNU/Linux è open source e quindi rispetto al software proprietario (ad esempio Windows) è possibile modificarlo dal codice sorgente, rendendolo alla portata delle proprie esigenze. Quindi se si hanno delle esigenze particolari o più semplicemente si vuole studiare il codice sorgente e fare delle piccole modifiche per imparare un linguaggio di programmazione da auto didatta con GNU/Linux si può fare, con altri progetti proprietari no.
Una cosa che si può fare, delle tante, con l’open source è la compilazione del kernel.
Ma prima. Che cos’è il kernel?
Il kernel è il componente principale di un sistema operativo. E’ il nucleo del sistema, che si interfaccia direttamente con la parte fisica del sistema (hardware), fornendo ai software in esecuzione le risorse necessarie per la corretta esecuzione e corretto funzionamento.
All’interno del kernel vi sono anche i driver, che non sono altro che moduli per permettere a questa parte software di riconoscere e poter comunicare con un determinato componente (che può essere ad esempio una scheda video o un hdd).
Si parla di comunicare perché ogni componente “parla” con un linguaggio macchina specifico, che ovviamente il kernel non può conoscere, in quanto è impossibile che li conosca tutti. Una volta che lo ha riconosciuto, non fa altro che fare da tramite tra il software in esecuzione e l’hardware. In poche parole virtualizza l’hardware, ricreandone uno fittizio che parla un linguaggio che possono capire tutti i programmi compatibili con quel determinato sistema operativo.
Ed è per questo che ci sono programmi compatibili per un sistema operativo e programmi compatibili con un altro sistema operativo. Perché non tutti comunicano con lo stesso linguaggio.
Ma il fatto dell’avvento del kernel e quindi dei sistemi operativi si è fatto un passo in avanti magnifico, in quanto non si devono più sviluppare programmi per ogni tipo di macchina o processore, ma un programma gira su tutti i tipi di computer (requisiti permettendo) a patto che sia compatibile con il sistema operativo installato sul PC.
I moduli del kernel
Il kernel Linux è composto da dei moduli, che sono delle micro aree contenenti drivers, funzioni di comunicazione, gestione del file system (gestore dell’archiviazione dei dati sul disco rigido).
Da questo schema è possibile vedere la struttura di un kernel. Nella parte più bassa dello schema troviamo l’hardware (quindi la RAM, CPU ecc…). Nella parte in altro troviamo i moduli per il Hardware support e Software support.
Nella sezione Hardware support, ci sono i vari drivers che riconoscono i componenti del computer e comunicano con il linguaggio del componente in questione. La sezione Software support praticamente fa da tramite tra le applicazioni e l’Hardware, traducendo il linguaggio dei vari componenti fisici in un linguaggio comune.
In poche parole fa da traduttore. Dato che i programmi non capiscono l’hardware e viceversa l’hardware non capisce il software, questi moduli comunicano le varie comunicazioni dell’hardware ai programmi e le comunicazioni dei programmi all’hardware.
Più in alto ci sono le Functionality, che sarebbe la gestione delle varie funzionalità del computer, come la connessione internet, il funzionamento della scheda video, del monitor ecc…
Ancora più in alto ci sono i Components, che sono i vari componenti di base del sistema, come il file system, la gestione della memoria, la gestione di internet (della connessione) e altre cose del genere.
Più in alto c’è la parte Applications, tools, che sono tutte le applicazioni che vengono eseguite dall’utente o in automatico tramite determinati processi. Tra il kernel e le applicazioni nell’area utente, ci sono le System Calls ovvero le chiamate al kernel, per i motivi che ho elencato prima, ovvero per comunicare dall’hardware al software e viceversa.
Questo schema potrebbe rendere meglio l’idea, in quanto è molto più semplificato e riassuntivo.
Qui notiamo una cosa nuova, ovvero che tra il kernel e la User Space si trova la libreria di comunicazione in linguaggio C (glibc). E’ la libreria che fornisce il linguaggio tra il kernel e le applicazioni. Non per tutte le applicazioni, ma per quasi tutte.
Queste cose che abbiamo appena visto saranno molto utili per capire il concetto di compilazione del kernel Linux e come si esegue.
Si lo so è un po’ complicato, ma è così e bisogna impararlo per poter agire direttamente sul kernel.
Detto queste premesse iniziamo.
Preparativi per la compilazione del kernel
Per prima cosa è necessario avere il sistema operativo su cui si vuole effettuare la modifica. Consiglio di fare questo procedimento su macchina virtuale, in modo che se ci siano dei problemi, il PC non verrà intaccato.
Il procedimento di questa guida verrà fatto su Ubuntu. Su altre distribuzioni però il procedimento è praticamente identico, a meno che non si vogliano fare delle cose particolarmente complesse.
Per prima cosa dobbiamo installare il pacchetto kernel-builder. Ci servirà per eseguire la compilazione. Per farlo apri un terminale e digita:
sudo apt-get install kernel-builder
Scaricare il sorgente del kernel
E’ possibile lavorare e compilare una copia del kernel “Vanilla”, ovvero quella in versione originale scaricabile dal sito kernel.org oppure scaricare una versione modificata dal team di Ubuntu o dal Team di Fedora ecc..
In questo caso, per scaricare la versione modificata dal team di Ubuntu è sufficiente installarla dal repository ufficiale durante i vari aggiornamenti, in quanto non sono disponibili sorgenti per compilare sulle versioni modificate.
Quindi per lavorarci, dovrete utilizzare le versioni Vanilla.
Una volta sul sito kernel.org cliccate sul pulsante giallo con scritto “Latest Kernel Stable” -> Ultima versione stabile del kernel e con il numero della versione.
La versione attuale del kernel disponibile (della data di pubblicazione di questo articolo) è la 4.2.3
Il sistema delle versioni
Le versioni del kernel seguono uno schema logico. Tutte le versioni che terminano con un numero dispari, come questa, sono versioni per sviluppatori e quindi versioni in cui il team sta testando nuovi moduli. Le versioni che terminano con un numero pari (es. 4.2.2) sono versioni più “stabili”. Sta a voi la scelta.
Estrarre il kernel dal pacchetto scaricato
Una volta scaricato l’archivio, è necessario estrarlo.
Per farlo bisogna aprire il file manager, andare nella cartella in cui si è salvato il file, cliccare con il tasto destro del mouse sull’archivio del kernel e dal menu a tendina su “Estrai qui”.
Spostare la cartella estratta
Una volta estratto il pacchetto, ci ritroveremo una cartella che dovremo spostare nella directory /usr/src
Per fare ciò aprire un terminale e digitare:
sudo su
cd /home/nome-cartella-home/nome-directory-cartella-estratta
mv linux-VERSIONE-SCARICATA /usr/src/
Entriamo nella cartella del kernel
Bene ora ci possiamo spostare nella directory /usr/src/linux-VERSIONE-SCARICATA
Per fare ciò si deve digitare:
cd /usr/src/linux-VERSIONE-SCARICATA
Iniziamo a modificare il kernel
Per iniziare dovremo digitare:
make config
Ed eccoci qui che ci ha aperto il file configurazione del kernel.
Piccola premessa
So che ormai sarete stanchi delle premesse, ma questa va fatta. Per salvare correttamente il file configurazione del kernel, sarà necessario settare tutti i parametri previsti. Ci vorranno, per fare un buon lavoro più di 6 ore. Calcolando però che molte impostazioni le dovrete cercare in rete, diciamo anche 10 o 12.
Quindi non è un’operazione che si fa in 2 minuti. Dovrete avere il tempo e la voglia di farlo. Se per caso si chiude involontariamente il file di configurazione dal terminale, si dovrà ricominciare tutto da capo.
Gli obiettivi
Prima di fare tutte queste operazioni, dovrete sapere perché lo state facendo, in modo che andrete a settare il kernel a seconda delle proprie esigenze.
Di solito si fa questa procedura per due scopi diversi.
- Il primo è quello di ottimizzare il kernel per il proprio computer. Infatti, come fa anche la Apple con il suo mac, sarà possibile adattare il kernel perfettamente all’hardware del proprio PC (quindi togliendo tutti i driver che non servono, tutte le funzioni che non servono e così via). Con queste operazioni il sistema operativo può diventare anche 8 volte più veloce e performante. Insomma, una cosa niente male.
- Il secondo è quello di realizzare un progetto che preveda delle funzioni particolari o preveda un sistema più leggero.
In tutti e due questi casi, questo procedimento è indispensabile. Quindi buona compilazione!
Iniziamo
Ah pensavi che l’articolo chiudesse qui. No, in realtà ho intenzione di guidarti fino alla fine. Online ho trovato molta documentazione, ma per lo più in inglese e quindi io sarò uno dei primi a scrivere un qualcosa di abbastanza completo. Dato che mi piace aiutare, ho deciso di fare una guida tutto sommato completa, che comprenda tutti i vari passaggi.
La prima domanda che ci pone il file di configurazione è se il kernel lo vogliamo o meno a 64 bit. Attenzione a rispondere, perché se il sistema operativo scaricato è a 32 bit e il kernel lo portate a 64 bit, ci saranno notevoli problemi, come la distruzione del sistema.
Rispondiamo a questa semplice domanda non n di no e y di yes.
Possiamo notare che nella risposta c’è una lettera più grande e una lettera più piccola. Quella più grande, è la risposta di default.
General Setup
La prima categoria è General Setup. Qui dovremo impostare le impostazioni generali del kernel.
- La prima cosa che ci chiederà il file è: Cross-compiler tool prefix (CROSS_COMPILE) []
Se non siete programmatori e non volete strumenti di compilazione nel kernel, premete semplicemente INVIO.
- Nella seconda: Compile also drivers which will not load (COMPILE_TEST) [N/y/?]
Se non servono driver per la compilazione, premete di no, quindi scrivete n. Se avete premuto invio nella prima, nella seconda è ovvio che la risposta è no.
- Local version – append to kernel release (LOCALVERSION) []. Qui dovrete digitare il nome della vostra versione modificata del Kernel. Potrete dare il nome che volete (tranne caratteri speciali, quali ?).
- Automatically append version information to the version string (LOCALVERSION_AUTO) [N/y/?] Qui vi chiede se volete far apparire il nome della versione nella stringa da terminale (es. con il comando uname-a). In questo caso io dico yes
- Ora bisogna scegliere l’opzione opportuna. Questo dipende da voi. Io lascerei l’opzione di default per non sbagliare.
Quindi premiamo 1 e poi invio.
- Default hostname (DEFAULT_HOSTNAME) [(none)] Nome del sistema host. Qui come nel caso della versione, possiamo inserire quello che si vuole.
- Support for paging of anonymous memory (swap) (SWAP) [Y/n/?] Supporto per la swap. Io voglio crearla e quindi yes
- System V IPC (SYSVIPC) [Y/n/?] Qui lascerei default.
- POSIX Message Queues (POSIX_MQUEUE) [Y/n/?] Qui io imposto no, in quanto non mi interessano i messaggi di sistema lato kernel (quali errori o problemi).
- Enable process_vm_readv/writev syscalls (CROSS_MEMORY_ATTACH) [Y/n/?] Qui io consiglio di lasciare nel default. Questi sono i processi per le virtual machines (macchine virtuali).
- open by fhandle syscalls (FHANDLE) [Y/n/?] Default
- uselib syscall (USELIB) [Y/n/?] Default. Questi sono sempre i moduli presenti per la macchina virtuale
- Enable system-call auditing support (AUDITSYSCALL) [Y/n/?] y Qui ho lasciato nel default, perché chiedeva se abilitare le chiamate del sistema. Come abbiamo visto in precedenza, sono fondamentali.
- Expose hardware/virtual IRQ mapping via debugfs (IRQ_DOMAIN_DEBUG) [N/y/?] Qui io disattivo questa impostazione in quanto non mi interessa nessun debug dei moduli dell’hadware
- Ora bisogna scegliere l’opzione opportuna. Questo dipende da voi. Io lascerei l’opzione di default per non sbagliare.
Io lascio l’opzione di default. In questo genere di scelta, a meno che non vi servano cose particolari, lasciate tutto di default.
- Old Idle dynticks config (NO_HZ) [Y/n/?] Qui chiede se vogliamo mantenere delle vecchie configurazione da determinati file di configurazione. Qui lo so, sono molto vago, ma non ho ancora capito se questi file provengano dal kernel precedentemente installato o da glibc. Dato che non ne sono convinto e per non rimanere nel dubbio io lascio l’opzione di default.
- High Resolution Timer Support (HIGH_RES_TIMERS) [Y/n/?] Questa opzione riguarda i processi e il tempo di esecuzione dei vari processi. Abilitare questa funzione soltanto per i computer nuovi o comunque recenti. Per i PC più datati lo sconsiglio, in quanto tende a mettere come prioritari l’esecuzione di molti processi e su processori vecchi potrebbe causare danni fisici (come rottura della ventola per surriscaldamento). Io in questo caso, avendo un PC nuovo, posso avere il lusso di attivarlo. E se avete intenzione di realizzare un progetto ed è pensato per macchine datate lasciatelo inattivo. Se invece è pensato per PC nuovi, beh allora potrete attivarlo tranquillamente.
CPU/Task time and stats accounting -> Processi della CPU e tempo di esecuzione
- Consiglio qui di scegliere l’alternativa di default
- BSD Process Accounting (BSD_PROCESS_ACCT) [Y/n/?] Queste sono impostazioni legate principalmente alla CPU. Io consiglio di stare nel default.
- BSD Process Accounting version 3 file format (BSD_PROCESS_ACCT_V3) [Y/n/?] Default
- Enable extended accounting over taskstats (TASK_XACCT) [Y/n/?] Default
- Enable per-task storage I/O accounting (TASK_IO_ACCOUNTING) [Y/n/?] Questo serve per la gestione Imput Output dei vari processi di archiviazione o gestione processi. Io scelgo l’opzione di default.
RCU Subsystem -> Sottosistema RCU
RCU: Read Copy Update -> Leggi, copia, aggiorna è un sistema presente nel kernel linux. Questo è un sistema molto esoso di risorse che si usa quando si devono eseguire solitamente nel sistema processi veramente molto pesanti. Infatti il kernel sarà predisposto a far elaborare alla CPU grandi quantità di dati tramite questo metodo. Sinceramente non lo gradisco molto e io nel mio caso lo disabilito. Anche perché è molto dispendioso di risorse.
- Make expert-level adjustments to RCU configuration (RCU_EXPERT) [N/y/?] (NEW) No
- Offload RCU callback processing from boot-selected CPUs (RCU_NOCB_CPU) [N/y/?] No
- Kernel .config support (IKCONFIG) [N/m/y/?] Qui chiede se vogliamo se il kernel avrà o meno il supporto di un file .config per configurare vari parametri (anche in modo automatico). Lo trovo un sistema molto dispendioso e poco utile. Quindi io lo disattivo.
- Kernel log buffer size (16 => 64KB, 17 => 128KB) (LOG_BUF_SHIFT) [17] Qui chiede la grandezza del file di log del kernel. Ogni valore corrisponde a una determinata grandezza in kb. Io lascio quella preimpostata. Se si vuole modificare, all’interno della parentesi tonda è presente una breve guida. Per lasciare il valore di default basta premere invio.
- CPU kernel log buffer size contribution (13 => 8 KB, 17 => 128KB) (LOG_CPU_MAX_BUF_SHIFT) [12] Qui chiede la grandezza del file di log per le informazioni che arrivano dalla CPU. Ricordo che il file di log è il file dove vengono memorizzati i vari errori o problematiche. Io imposto un bel 17, per avere un file di log abbastanza grande per tutte le eventuali informazioni.
Control Group support -> Supporto del gruppo di controllo
- Example debug cgroup subsystem (CGROUP_DEBUG) [N/y/?] Qui ci chiede se vogliamo una funzione di debug o verifica per un sottosistema di controllo. Le funzioni di debug sono importanti, ok, ma consumano molte risorse. Pertanto, io lo lascio disattivato.
- Freezer cgroup subsystem (CGROUP_FREEZER) [Y/n/?] Io qui disabilito questo modulo, in quanto non mi serve questo tipo di sottosistema.
- Device controller for cgroups (CGROUP_DEVICE) [Y/n/?] Abilitiamo il controllo dei devices (dispositivi) per cgroups.
- Cpuset support (CPUSETS) [Y/n/?] Default
- Include legacy /proc/<pid>/cpuset file (PROC_PID_CPUSET) [Y/n] Io in questo caso includo il file cpuset (che sono importanti informazioni tecniche per il kernel riguardanti la CPU).
- Simple CPU accounting cgroup subsystem (CGROUP_CPUACCT) [Y/n/?] Qui dato che è un controllo sul processore lascio l’impostazione di default
- Memory Resource Controller for Control Groups (MEMCG) [Y/n/?] Questo modulo permette di abilitare o meno il controllo sulle risorse della memoria (RAM) per la CPU e per il gruppo di controllo della CPU. Io lascio l’impostazione di default.
- Memory Resource Controller Swap Extension (MEMCG_SWAP) [Y/n/?] Stessa cosa, ma questa volta sul controllo della memoria swap. Default
- Memory Resource Controller Swap Extension enabled by default (MEMCG_SWAP_ENABLED) [N/y/?] In questo caso questo lo lasciamo disattivato, in quanto altrimenti la SWAP sarebbe sempre la memoria principale, quando dovrebbe essere la RAM. Il PC diventerebbe di un lento che non si può usare.
- Memory Resource Controller Kernel Memory accounting (MEMCG_KMEM) [Y/n/?] Default. Questa è per il controllo della RAM che userà direttamente il kernel.
- HugeTLB Resource Controller for Control Groups (CGROUP_HUGETLB) [Y/n/?] Default
- Anche la prossima la lasciamo di default.
Group CPU scheduler
Per sapere di più su questo modulo visitare questa pagina del sito di kernel.org
- CPU bandwidth provisioning for FAIR_GROUP_SCHED (CFS_BANDWIDTH) [Y/n/?] Questo modulo imposta la larghezza di banda della CPU per un modulo del kernel chiamato CPU scheduler. Dato che ultimamente sta dando diversi problemi, io lo disabilito.
- Quindi disabilitiamo anche il prossimo modulo: Group scheduling for SCHED_RR/FIFO (RT_GROUP_SCHED) [N/y/?]
- Block IO controller (BLK_CGROUP) [Y/n/?] Questo modulo è essenziale che rimanga attivo. Questo modulo tra le tante cose che fa (questo è uno dei moduli più grandi presenti nel kernel Linux) isola i processi critici di sistema o quelli problematici per non fare mandare in crash l’intero sistema operativo. Isola i processi delle macchine virtuali per garantirgli più prestazioni. Note in più. Questo modulo fu inventato da Ryo Tsuruta e Hirokazu Takahashi. Furono anche implementati da loro nel Kernel. Questo modulo del kernel ovviamente lo attiviamo. Per maggiori informazioni su questo modulo guardare questo documento pdf
- Enable Block IO controller debugging (DEBUG_BLK_CGROUP) [N/y/?] Io il debug di questo modulo non lo voglio e quindi mi attengo al default. NO!
- Checkpoint/restore support (CHECKPOINT_RESTORE) [Y/n/?] Questo modulo permette al programmatore di creare un backup di emergenza (punto di ripristino) in caso di danni gravi al sistema. Tutto il procedimento andrà fatto a mano dal terminale. Dato che a me non mi importa, lo disabilito.
Namespaces support
- Namespaces support (NAMESPACES) [Y/n/?] Default
- Qui ci saranno le varie impostazioni e varianti di questo modulo. Consiglio di attivare i primi 4. Gli ultimi 2 di disattivarli.
- Initial RAM filesystem and RAM disk (initramfs/initrd) support (BLK_DEV_INITRD) [Y/n/?] y Qui serve per dare un valore di partenza al gestore della RAM ad ogni avvio del sistema. Consiglio di attivare questa funzione.
- Initramfs source file(s) (INITRAMFS_SOURCE) [] Qui c’è un valore di partenza da dare. Questo non posso aiutarvi, dipende dal vostro PC o dal progetto che volete creare.
- Support initial ramdisks compressed using gzip (RD_GZIP) [Y/n/?] Default
- Support initial ramdisks compressed using bzip2 (RD_BZIP2) [Y/n/?] Questo io lo disattivo in quanto in precedenza avevamo scelto soltanto il formato gzip. E quindi questo è inutile (secondo me).
- Anche i prossimi moduli, fino alla fine di questa piccola sessione, io li ho disattivati.
Configure standard kernel features (expert users) -> Configurazione avanzata del kernel (solo per utenti esperti)
Questa sessione sarebbe meglio farla, ma non posso aiutarvi in quanto dipende tutto dal vostro PC o dal vostro progetto. Se non siete utenti molto esperti nel primo modulo digitate n per saltare questa configurazione (con il rischio che il sistema potrebbe avere seri problemi, perché non configurato per il sistema operativo attuale). Da ricordarsi che questa è la versione del kernel Vanilla e non una modificata dal team della vostra distribuzione.
- Include all symbols in kallsyms (KALLSYMS_ALL) [Y/n/?] In questo caso se per caso non avete scelto la configurazione avanzata, attivate questo modulo. Oppure non saprei, dipende dalle vostre modifiche apportate in precedenza.
- Enable bpf() system call (BPF_SYSCALL) [Y/n/?] Default
- Embedded system (EMBEDDED) [N/y/?] Io questo modulo lo disattiverei, in quanto lo ritengo molto pesante
- Debug: use vmalloc to back perf mmap() buffers (DEBUG_PERF_USE_VMALLOC) [N/y/?] Modulo di debug. Io lo disabilito. Una cosa importante da notare sul file di configurazione del kernel è che se si disattivano i primi moduli di debug, i prossimi presenti li mette disabilitati di default. Stessa cosa anche per i driver.
- Disable heap randomization (COMPAT_BRK) [N/y/?] Default
- Qui consiglio di scegliere l’impostazione di default
- SLUB per cpu partial cache (SLUB_CPU_PARTIAL) [Y/n/?] Io questo lo lascerei abilitato come da default
- I prossimi moduli presenti non ci sono controindicazioni. Potrete lasciare nel default, fino all’inizio della prossima sezione Poi ovviamente dipende da quello che dovrete fare.
GCOV-based kernel profiling
- Enable gcov-based kernel profiling (GCOV_KERNEL) [N/y/?] Io questo modulo lo disabiliterei. Questo è un modulo che funziona tramite GCC (il compilatore C) in quanto produce molti moduli in questo linguaggio. Lo stesso modulo è scritto in C-C++. Questo modulo può essere usato da chi vuole eseguire debug a vari moduli del kernel o a varie applicazioni (avrete ben potuto notare che non è il mio caso), sviluppatori, tester di sistemi (beta tester o altri di questo genere). Questo modulo produce dei file (simili ai file di log) scritti in C sul funzionamento di vari componenti. I file generati è possibile prelevarli in /tmp/linux-out. Volendo questi moduli è possibile anche compilarli con il comando
gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c
Per saperne di più basta che vai a vedere questa documentazione sul sito kernel.org
Enable loadable module support
- Enable loadable module support (MODULES) [Y/n/?] Default
Il resto delle impostazioni che ho selezionato, le potrete vedere da questo screen
Enable the block Layer
In questa sessione c’è da fare poco o nulla. Io mi sono mantenuto ai default.
Bene. Per il resto della configurazione del kernel non posso aiutarvi, in quanto dipende tutto dal vostro PC, dal vostro progetto e dalle vostre esigenze. Io vi ho aiutato nella configurazione di base. Il resto è una selezione di driver e altro.
Per non sbagliare
Ricordatevi di abilitare i driver del vostro hard disk, del vostro processore, della vostra scheda grafica, rete e così via. Se avete delle porte USB nel PC abilitate il giusto driver.
Per i lettori ottici è la medesima cosa.
Abilitate il GRUB, il boot loader, il gestore di avvio.
Disabilitate tutti i driver che non vi servono o che non appartengono al vostro PC. Es. Se avete il processore della intel, i driver della AMD non vi serviranno a nulla. Se non lo fate. la compilazione del kernel è inutile e potevate anche non farla.
Ricordatevi di scegliere i moduli opportuni per raggiungere le vostre necessità, quelle che vi hanno spinto ad intraprendere questa fase.
Una volta configurato il tutto dovrete passare alla compilazione
Compiliamo il Kernel
Per compilare, sempre da root e da terminale, digitare
make-kpkg --rootcmd fakeroot --initrd kernel_image kernel_headers modules_image
La compilazione su PC abbastanza potenti dura 4 o 5 orette. Ma se avete PC poco potenti potrebbe metterci anche 10 ore.
Installiamo il kernel compilato
Una volta finita la compilazione, nella cartella /usr/src/ saranno presenti 2 file, che sarebbero i due eseguibili (nel caso di Ubuntu .deb del kernel. Dovrete andare ad installarli, come se fossero normali file .deb, quindi o con il software center, o con gDebi o con il terminale. A voi la scelta.
Con questo direi che potrei anche chiudere qui l’articolo. Spero che vi sia stato utile e con questo vi aspetto al prossimo. Ciao 🙂