Supponiamo di voler aggiungere alcune funzionalità extra nel kernel Linux.
Quindi la prima idea che viene in mente è quella di migliorare il kernel aggiungendo più codice, compilando il codice e aggiornando il nuovo kernel.
Ma questo processo ha i seguenti inconvenienti tra molti altri:
- Il codice aggiunto aumenta la dimensione del kernel in modo permanente.
- L'intero kernel deve essere nuovamente compilato affinché le modifiche vengano compilate.
- Ciò significa che la macchina deve essere riavviata affinché le modifiche abbiano effetto.
La soluzione ai problemi di cui sopra è il concetto di LKM.
LKM sta per moduli del kernel caricabili (LKM). Come suggerisce il nome, gli LKM sono i moduli che possono essere caricati direttamente nel kernel in fase di esecuzione.
Il modulo del kernel caricabile supera tutte le carenze sopra menzionate.
- Il modulo può essere compilato separatamente
- Il modulo può essere caricato sul kernel in fase di esecuzione senza dover riavviare la macchina.
- Il modulo può essere scaricato in qualsiasi momento e quindi nessun effetto permanente sulla dimensione del kernel.
Come creare LKM
Creiamo un modulo del kernel caricabile di base.
#include <linux/module.h> #include <linux/kernel.h> int init_module(void) { printk(KERN_INFO "Welcome.....\n"); return 0; } void cleanup_module(void) { printk(KERN_INFO "Bye....\n"); }
Quindi vediamo che il codice sopra è un LKM di base.
- I nomi 'init_module' e 'cleanup_module' sono nomi standard per un LKM.
- Se guardi da vicino, scoprirai che abbiamo usato 'printk' invece di 'printf'. Questo perché non è una normale programmazione C, è una programmazione a livello di kernel che è un po' diversa dalla normale programmazione a livello di utente.
- Le intestazioni module.h e kernel.h devono essere incluse per ottenere il codice compilato.
Come compilare LKM
Per compilare l'LKM sopra, ho usato il seguente Makefile:
obj-m += lkm.o all: sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Tieni presente che i comandi che iniziano con la parola chiave "sudo" sopra devono avere uno spazio di tabulazione da sinistra.
Quindi, quando viene eseguito il comando precedente, viene osservato il seguente output:
make: Entering directory `/usr/src/linux-headers-2.6.32-21-generic' CC [M] /home/himanshu/practice/lkm.o Building modules, stage 2. MODPOST 1 modules CC /home/himanshu/practice/lkm.mod.o LD [M] /home/himanshu/practice/lkm.ko make: Leaving directory `/usr/src/linux-headers-2.6.32-21-generic'
Dopo la compilazione riuscita di cui sopra, troverai un file .ko nella stessa directory in cui è avvenuta la compilazione.
Questo file .ko è il modulo che verrà caricato nel kernel. L'utilità modinfo può essere utilizzata per recuperare le informazioni su questo modulo:
$ modinfo lkm.ko filename: lkm.ko srcversion: 19967CB3EAB7B31E643E006 depends: vermagic: 2.6.32.11+drm33.2 SMP mod_unload modversions
Quindi vediamo che l'utilità 'modinfo' fornisce alcune informazioni su questo modulo.
Come viene caricato LKM
Dopo una corretta compilazione e creazione del modulo, ora è il momento di inserirlo nel kernel in modo che venga caricato in fase di esecuzione. L'inserimento del modulo può essere realizzato utilizzando le seguenti due utilità :
- modprobe
- insmod
La differenza tra i due sta nel fatto che "modprobe" si prende cura del fatto che se il modulo dipende da qualche altro modulo, allora quel modulo viene prima caricato e quindi viene caricato il modulo principale. Mentre l'utilità 'insmod' inserisce semplicemente il modulo (il cui nome è specificato) nel kernel.
Quindi "modprobe" è un'utilità migliore, ma poiché il nostro modulo non dipende da nessun altro modulo, utilizzeremo solo "insmod".
Quindi, per inserire il modulo, viene utilizzato il seguente comando:
$ sudo insmod ./lkm.ko
se questo comando non dà alcun errore, significa che LKM è stato caricato correttamente nel kernel.
Per scaricare l'LKM, viene utilizzato il seguente comando:
$ sudo rmmod lkm.ko
Anche in questo caso, se questo comando non fornisce alcun errore, significa che LKM è stato scaricato correttamente nel kernel.
Per verificare che il modulo sia stato caricato e scaricato correttamente possiamo usare l'utility dmesg che fornisce l'ultimo set di log come loggato dal kernel. Vedrai le seguenti due righe tra tutti gli altri registri:
.... .... [ 4048.333756] Welcome..... [ 4084.205143] Bye....
Se torni al codice e vedi, ti renderai conto che questi sono i log delle due funzioni nel codice.
Quindi vediamo che una funzione è stata chiamata quando è stato chiamato "insmod" e l'altra funzione è stata chiamata quando è stato chiamato "rmmod".
Questo era solo un LKM fittizio. In questo modo molti LKM funzionanti (che svolgono attività significative) lavorano all'interno del kernel Linux.