LKMPG: Ciao Mondo: differenze tra le versioni

nessun oggetto della modifica
(Nuova pagina: {{Template:LKMPG}})
 
Nessun oggetto della modifica
Riga 1: Riga 1:
{{Template:LKMPG}}
{{Template:LKMPG}}
==Hello, World (parte 1): Il modulo più semplice==
Quando il primo programmatore delle caverne scolpì il primo programma sul muro del primo computer delle caverne, fu un programma che disegnava la stringa "Hello, world" in __Antelope pictures__. I libri di testo romani sulla programmazione iniziano con il programma "Salut, Mundi". Non so cosa possa succedere alle persone che rompono questa tradizione, ma penso sia più sicuro non scoprirlo. Inizieremo con una serie di programmi "hello world" che mostrano vari aspetti delle conoscenze di base nella scrittura di moduli del kernel.
Qui vediamo il modulo più semplice possibile. Non compilarlo ancora; analizzeremo la compilazione di un modulo nella prossima sezione.
Esempio 2-1. hello-1.c
<pre>
/* 
*  hello-1.c - Il modulo più semplice.
*/
#include <linux/module.h> /* Necessario a tutti i moduli */
#include <linux/kernel.h> /* Necessario per la macro KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
/*
* Un valore di ritorno diverso da 0 indica che init_module è fallita; il modulo non può essere caricato
*/
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
</pre>
I moduli del kernel devono avere almeno due funzioni. Una funzione "iniziale" (inizializzazione) detta <code>init_module()</code> che è chiamata quando il modulo è inserito nel kernel tramite insmod, e una funzione "finale" (di pulizia) detta <code>cleanup_module()</code> che è chiamata prima che il modulo venga rimosso con rmmoded. In realtà, le cose sono cambiate a partire dal kernel 2.3.13. Puoi utilizzare qualunque nome ti piaccia per la funzione di inizializzazione e di cleanup, e imparerai a farlo nella Sezione XXXX2.3XXXX. Infatti, il nuovo metodo è quello preferito. Comunque, molti continuano ad utilizzare init_module() e cleanup_module() per le proprie funzioni iniziali e finali.
Tipicamente, <code>init_module()</code> o registra un handler con il kernel per fare una serie di azioni, oppure rimpiazza una della funzioni del kernel stesso con un codice proprio (usualmente questo codice fa una serie di azioni e poi chiama la funzione originale). Si suppone che la funzione <code>cleanup_module()</code> disfaccia tutto ciò che ha fatto <code>init_module()</code>, in modo tale che il modulo possa essere rimosso tranquillamente.
Infine, ogni modulo del kernel ha bisogno di includere <code>linux/module.h</code>. Nell'esempio abbiamo dovuto includere <code>linux/kernel.h</code> solo per la macro <code>KERN_ALERT</code> utilizzata per definire il livello di log della <code>printk()</code>, che imparerai nella Sezione XXXX.
===Introduzione a <code>printk()</code>===
Nonostante quello che si potrebbe pensare, <code>printk()</code> non aveva lo scopo di comunicare informazioni all'utente, anche se l'abbiamo utilizzato esattamente per questo in <code>hello-1</code>! E' stato pensato, invece, per essere un meccanismo di logging per il kernel, ed è utilizzato per loggare informazioni e mostrare dei warning. Perciò, ogni dichiarazione di <code>printk()</code> viene fornita di un livello di priorità, che, nell'esempio, è la <code>KERN_ALERT</code> (<code><1></code>). Ci sono 8 priorità e il kernel possiede delle macro per queste, quindi non c'è il bisogno di utilizzare numeri criptici. Si possono vedere le macro (e il loro significato) nel file <code>linux/kernel.h</code>. Se non si specifica un livello di priorità, verrà utilizzata quella di default: <code>DEFAULT_MESSAGE_LOGLEVEL</code>.
E' importante prestare una certa attenzione nel leggere le macro di priorità. L'header file descrive anche cosa significa ogni priorità. In pratica, è bene non utilizzare i numeri, come <code><4></code>. Si utilizzino sempre le macro, come <code>KERN_WARNING</code>.
Se la priorità è minore di <code>int console_loglevel</code>, il messaggio è stampato sul proprio terminale corrente. Se sia '''syslogd''' che klogd stanno girando, allora il messaggio verrà inserito in coda a <code>/var/log/messages</code>, indipendentemente dal fatto che venga stampato sulla console. Nell'esempio abbiamo utilizzato una priorità alta, come <code>KERN_ALERT</code>, per essere sicuri che il messaggio di printk() venga stampato sulla console piuttosto che inserito nel file di log. Quando si scrivono moduli reali, si utilizzano le priorità che meglio si adattano alla situazione in esame.
168

contributi