LKMPG: Ciao Mondo: differenze tra le versioni

nuova categoria
(nuova categoria)
 
(9 versioni intermedie di 3 utenti non mostrate)
Riga 1: Riga 1:
{{Template:LKMPG}}
{{Template:LKMPG}}
==Ciao, Mondo (parte 1): Il modulo più semplice==
==Ciao, Mondo (parte 1): Il modulo più semplice==


Riga 119: Riga 118:
==Ciao, Mondo (parte 2)==
==Ciao, Mondo (parte 2)==


Dalla versione 2.4 del kernel Linux, si possono rinominare le funzioni di init e cleanup dei propri moduli; infatti non devono essere chiamate per forza rispettivamente <code>init_module()</code> e <code>cleanup_module</code>. Questo è reso possibile della macro <code>module_init()</code> e module_exit()</code>. Queste macro sono definite in <code>linux/init.h</code>. L'unica attenzione da avere è quella di definire le funzioni di init e cleanup prima di chiamare le macro, pena errori di compilazione. Vediamo un esempio di questa tecnica:
Dalla versione 2.4 del kernel Linux, si possono rinominare le funzioni di init e cleanup dei propri moduli; infatti non devono essere chiamate per forza rispettivamente <code>init_module()</code> e <code>cleanup_module</code>. Questo è reso possibile della macro <code>module_init()</code> e <code>module_exit()</code>. Queste macro sono definite in <code>linux/init.h</code>. L'unica attenzione da avere è quella di definire le funzioni di init e cleanup prima di chiamare le macro, pena errori di compilazione. Vediamo un esempio di questa tecnica:


'''Esempio 3-3. hello-2.c'''
'''Esempio 3-3. hello-2.c'''
Riga 488: Riga 487:


==Creare moduli per kernel precompilati==
==Creare moduli per kernel precompilati==
Ovviamente, raccomandiamo fortemente di ricompilare il tuo kernel in modo da abilitare un certo numero di caratteristiche di debugging utili, come MODULE_FORCE_UNLOAD (forzare l'unload di moduli): quando questa opzione è abilitata, puoi forzare il kernel a rimuovere un modulo, anche quando crede (il kernel, n.r.d.) che non è sicuro, tramite il comando '''rmmod -f module'''. Questa opzione può farti risparmiare tanto tempo ed un certo numero di riavvii durante lo sviluppo di un modulo.
Tuttavia, ci sono alcuni casi in cui si voglia caricare un modulo in un kernel precompilato in esecuzione, come per esempio quelli forniti nelle comuni distribuzioni Linux, o in un kernel compilato tempo fa. In alcune circostanze potresti avere la necessità di compilare ed inserire un modulo in un kernel in esecuzione che non hai il permesso di ricompilare, o su una macchina che preferiresti non riavviare. Se non riesci a pensare ad un caso che ti costringerà ad usare moduli per un kernel precompilato, potresti voler saltare questa sezione e trattare il resto di questo capitolo come una grande nota a pie' di pagina.
Ora, se hai appena installato un kernel da sorgente, usalo per compilare i tuoi moduli e prova ad inserirli nel kernel; in molti casi potresti ottenere un errore come il seguente:
<pre>
insmod: error inserting 'poet_atkm.ko': -1 Invalid module format
</pre>
Informazioni meno criptiche sono presenti in /var/log/messages:
<pre>
Jun  4 22:07:54 localhost kernel: poet_atkm: version magic '2.6.5-1.358custom 686
REGPARM 4KSTACKS gcc-3.3' should be '2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3'
</pre>
In altre parole, il kernel si rifiuta di accettare il modulo per via delle versioni (più precisamente, magics version) che non corrispondono. Per inciso, le version magics sono conservate nell'oggetto del modulo come stringa statica che inizia per vermagic:. Le informazioni di versione sono inserite nel tuo modulo quando è linkato al file <code>init/vermagic.o</code>. Per dare uno sguardo alle version magics ed altre stringhe conservate in un modulo, puoi dare il comando '''modinfo module.ko''':
<pre>
[root@pcsenonsrv 02-HelloWorld]# modinfo hello-4.ko
license:        GPL
author:        Peter Jay Salzman <p@dirac.org>
description:    A sample driver
vermagic:      2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3
depends:       
</pre>
Per superare questo problema possiamo ricorrere all'opzione --force-vermagic, ma questa soluzione è potenzialmente insicura, e indiscutibilmente inaccettabile nella produzione di moduli. Di conseguenza, vogliamo compilare il nostro modulo in un ambiente che sia identico a quello in cui il nostro kernel precompilato è stato costruito. Come fare questo è il tema del resto del capitolo.
Prima di tutto, assicurarsi che il codice sorgente del kernel è disponibile e che abbia esattamente la stessa versione del kernel in esecuzione. Dunque, trova il file di configurazione che è stato usato per compilare il kernel precompilato. Di solito, è disponibile nella directory <code>/boot</code>, sotto un nome tipo config-2.6.x. Potresti volerlo copiare nella directory del kernel: '''cp /boot/config-`uname -r` /usr/src/linux-`uname -r`/.config'''.
Concentriamoci di nuovo sul precedente errore: uno sguardo da vicino alle stringhe version magic suggeriscono che, anche con due file di configurazione che sono esattamente gli stessi, una piccola differenza nel version magic è possibile, ed è sufficiente a prevenire l'inserimento del modulo nel kernel. Questa piccola differenza, cioè la stringa personalizzata che appare nel version magic del modulo e non in quella del kernel, è dovuta ad una modifica nel makefile, che alcune distribuzioni includono, rispetto all'originale. Quindi, esamina il tuo <code>/usr/src/linux/Makefile</code> ed assicurati che l'informazione della versione specificata è esattamente la stessa di quella usata per il tuo kernel corrente. Per esempio, il tuo makefile potrebbe iniziare cosi:
<pre>
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 5
EXTRAVERSION = -1.358custom
...
</pre>
In questo caso, hai bisogno di ripristinare il valore del simbolo EXTRAVERSION a -1.358. Suggeriamo di tenere una copia di backup del makefile usato per compiare il tuo kernel disponibile in <code>/lib/modules/2.6.5-1.358/build</code>. Un semplice '''cp /lib/modules/`uname -r`/build/Makefile /usr/src/linux-`uname -r`''' dovrebbe essere sufficiente. Inoltre, se hai già inziato a compilare il kernel con il precedente (sbagliato) Makefile, dovresti anche rieseguire '''make''', o modificare direttamente il simbolo UTS_RELEASE nel file <code>/usr/src/linux-2.6.x/include/linux/version.h</code> con lo stesso valore presente in <code>/lib/modules/2.6.x/build/include/linux/version.h</code>, o sovrascrivere quest'ultimo sul primo.
Ora, eseguire '''make''' per aggiornare la configurazione, la versione degli headers e gli oggetti:
<pre>
[root@pcsenonsrv linux-2.6.x]# make
CHK    include/linux/version.h
UPD    include/linux/version.h
SYMLINK include/asm -> include/asm-i386
SPLIT  include/linux/autoconf.h -> include/config/*
HOSTCC  scripts/basic/fixdep
HOSTCC  scripts/basic/split-include
HOSTCC  scripts/basic/docproc
HOSTCC  scripts/conmakehash
HOSTCC  scripts/kallsyms
CC      scripts/empty.o
...
</pre>
Se non desideri compiare il kernel ora, puoi interrompere il processo ('''CTRL-C''') subito dopo la linea che inizia per <code>SPLIT</code> poichè in quel momento i file che ti servono saranno già pronti. Ora puoi tornare indietro alla directory del tuo modulo e compilarlo: sarà compilato correttamente in accordo con le impostazioni del tuo kernel corrente e verrà caricato senza nessun errore.
[[Categoria:Linux Kernel Module Programming Guide]]
6 999

contributi