Un modulo del kernel è un po' di codice compilato che può essere inserito nel kernel in fase di esecuzione, come con insmod
o modprobe
.
Un driver è un pezzo di codice che viene eseguito nel kernel per comunicare con un dispositivo hardware. "Guida" l'hardware. La maggior parte dell'hardware nel tuo computer ha un driver associato.¹ Gran parte di un kernel in esecuzione è il codice del driver.²
Un driver può essere compilato staticamente nel file del kernel su disco.³ Un driver può anche essere compilato come modulo del kernel in modo che possa essere caricato dinamicamente in un secondo momento. (E poi forse scaricato.)
La pratica standard è costruire i driver come moduli del kernel ove possibile, piuttosto che collegarli staticamente al kernel, poiché ciò offre maggiore flessibilità. Tuttavia, ci sono buone ragioni per non farlo:
-
A volte un determinato driver è assolutamente necessario per aiutare il sistema ad avviarsi. Ciò non accade così spesso come potresti immaginare, a causa della funzione initrd.
-
I driver costruiti in modo statico possono essere esattamente ciò che si desidera in un sistema con ambito statico, come un sistema incorporato. Vale a dire, se sai in anticipo esattamente quali driver saranno sempre necessari e che questo non cambierà mai, hai una buona ragione per non preoccuparti dei moduli dinamici del kernel.
-
Se si compila il kernel in modo statico e si disabilita la funzione di caricamento dinamico dei moduli di Linux, si impedisce la modifica in fase di esecuzione del codice del kernel. Ciò fornisce ulteriore sicurezza e stabilità a scapito della flessibilità.
Non tutti i moduli del kernel sono driver. Ad esempio, una funzionalità relativamente recente nel kernel di Linux è che puoi caricare uno scheduler di processo diverso. Un altro esempio è che i tipi di hardware più complessi hanno spesso più livelli generici che si trovano tra il driver hardware di basso livello e lo spazio utente, come il driver USB HID, che implementa un particolare elemento dello stack USB, indipendente dall'hardware sottostante.
A parte:
-
Un'eccezione a questa affermazione generica è il chip della CPU, che non ha un "driver" di per sé . Il tuo computer potrebbe anche contenere hardware per il quale non hai driver.
-
Il resto del codice in un kernel del sistema operativo fornisce servizi generici come la gestione della memoria, l'IPC, la pianificazione, ecc. infrastruttura del kernel.
-
Quello in
/boot
, caricato nella RAM al momento dell'avvio dal boot loader all'inizio del processo di avvio.
Per rispondere alla tua domanda specifica sul lspci
output, la riga "kernel driver" si riferisce a quale driver è attualmente associato alla scheda, in questo caso il proprietario nvidia
autista. La riga "moduli del kernel" elenca tutti i driver noti per essere in grado di legarsi a questa carta. Qui, il driver proprietario mostra un nome diverso, probabilmente a causa di come lspci
ha trovato il driver e il suo nome file rispetto al nome codificato nel driver stesso.
Un modulo del kernel potrebbe non essere affatto un driver di dispositivo
"Kernel driver" non è un termine ben definito, ma proviamoci.
Questo è un modulo del kernel che non guida alcun hardware, e quindi non può essere ragionevolmente considerato un "driver di dispositivo":
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
static int myinit(void)
{
printk(KERN_INFO "hello init\n");
return 0;
}
static void myexit(void)
{
printk(KERN_INFO "hello exit\n");
}
module_init(myinit)
module_exit(myexit)
Dopo la compilazione, puoi usarlo con:
insmod hello.ko
e stampa hello init
a dmesg
.
Esistono, tuttavia, moduli del kernel che non sono driver di dispositivo, ma in realtà sono utili, ad esempio moduli che espongono il debug del kernel / informazioni sulle prestazioni.
Di solito i driver di dispositivo sono anche moduli del kernel.
Un esempio di qualcosa che è un "driver di dispositivo" è un po' più difficile da generare, poiché richiede un hardware da guidare e le descrizioni dell'hardware tendono a essere complicate.
Utilizzando QEMU o altri emulatori, tuttavia, possiamo costruire modelli software di hardware reale o semplificato, che è un ottimo modo per imparare a parlare con l'hardware. Ecco un semplice esempio di un driver di dispositivo PCI minimo:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/hello.c
Vediamo poi che in x86, parlare con l'hardware si riduce a:
in
eout
istruzioni, ad esempio https://stackoverflow.com/questions/3215878/what-are-in-out-instructions-in-x86-used-for/33444273#33444273- gestire gli interrupt registrando i gestori con la CPU
Queste operazioni in generale non possono essere eseguite da userland, come spiegato in:Qual è la differenza tra spazio utente e spazio kernel? Esistono tuttavia alcune eccezioni:https://stackoverflow.com/questions/7986260/linux-interrupt-handling-in-user-space.
Il kernel offre quindi API di livello superiore per rendere tale interazione hardware più semplice e portabile:
request_irq
per gestire gli interruptioreadX
e mappatura della memoria IO- interfacce di livello superiore per protocolli popolari come PCI e USB