In breve :tu difficilmente può scrivere utili moduli del kernel, che possono essere caricati su kernel di una gamma relativamente ampia di versioni.
Quando compili il modulo rispetto al kernel compilato con CONFIG_MODVERSIONS
(come nel tuo caso), per ogni simbolo, esportato dal kernel, il CRC per questo simbolo è memorizzato nel file del modulo. CRC è una sorta di somma di controllo , che tiene conto, tra l'altro, del layout dei tipi, utilizzato per i parametri della funzione. Ad esempio, se il layout di un ipotetico struct A
differisce in due kernel, CRC per la funzione f(struct A *a)
anche in questi kernel differisce.
Quando un modulo viene caricato nel kernel in esecuzione, i CRC per tutte le funzioni nel modulo vengono confrontati con quelli del kernel. Se differiscono, il kernel si rifiuta di caricare il modulo. Per saperne di più su questo meccanismo, consulta la documentazione del kernel (Documentation/kbuild/modules.txt).
Quindi, per rendere un modulo caricabile in due kernel diversi, sei limitato solo con funzioni i cui parametri hanno lo stesso layout in entrambi i kernel. In particolare, se layout di tipo struct module
differisce, nessun singolo modulo può essere caricato per entrambi i kernel.
Esistono diversi approcci per fornire un driver adatto a diversi kernel. Il modo più semplice è fornire le fonti del conducente e aggiungili a dkms
. In questo modo, se il kernel in esecuzione non ha il driver compilato, il driver verrà compilato automaticamente utilizzando le sue fonti.