43
contributi
Riga 300: | Riga 300: | ||
==Passare argomenti ad un modulo da linea di comando== | ==Passare argomenti ad un modulo da linea di comando== | ||
I moduli possono prendere argomenti da linea di comando, ma non tramite argc/argv come potresti essere abituato a fare. | |||
Per passare argomenti al tuo modulo, bisogna dichiarare una variabile globale che assumerà il valore passato da linea di comando e usare la macro <code>module_param()</code> (definita in <code>linux/moduleparam.h</code>) per impostare il meccanismo d'associazione. A runtime, insmod copierà l'argomento da linea di comando passato al modulo nella variabile globale dichiarata come per esempio '''./insmod mymodule.ko myvariable=5'''. La dichiarazione della variabile e le macro dovrebbero essere poste all'inizio del modulo, per chiarezza. L'esempio dovrebbe chiarire la mia pessima spiegazione. | |||
La macro <code>module_param()</code> prende 3 argomenti: il nome della variabile, il suo tipo e i permessi per il corrispondente file in sysfs. Le variabili di tipo integer possono essere signed (come al solito) o unsigned. Se preferisci usare array di interi o stringhe, dai uno sguardo a <code>module_param_array()</code> e <code>module_param_string()</code>. | |||
<pre> | |||
int myint = 3; | |||
module_param(myint, int, 0); | |||
</pre> | |||
Anche gli array sono supportati, ma le cose sono leggermente differenti ora rispetto a come lo erano nei giorni del kernel 2.4. Per tenere traccia dei numeri di parametri è necessario passare un puntatore ad una variabile di conteggio come terzo parametro. A tua scelta, puoi ignorare il conteggio e passare NULL invece. Noi mostriamo entrambe le possibilità qui: | |||
<pre> | |||
int myintarray[2]; | |||
module_param_array(myintarray, int, NULL, 0); /* not interested in count */ | |||
int myshortarray[4]; | |||
int count; | |||
module_parm_array(myshortarray, short, , 0); /* put count into "count" variable */ | |||
</pre> | |||
Un buon utilizzo è di avere un valore di default per la variabile settato, come una porta o un indirizzo IO. Se le variabili contengono il valore di default, allora eseguire l'autoriconoscimento (spiegato da qualche parte). Altrimenti, mantenere il valore corrente. Tutto questo sarà chiarito in seguito. | |||
Infine, c'e' una maco, <code>MODULE_PARM_DESC()</code> che è usata per documentare gli argomenti che il modulo accetta. La macro prende due parametri: un nome di variabile e una descrizione della variabile. | |||
'''Esempio 2-7. hello-5.c''' | |||
<pre> | |||
/* | |||
* hello-5.c - Demonstrates command line argument passing to a module. | |||
*/ | |||
#include <linux/module.h> | |||
#include <linux/moduleparam.h> | |||
#include <linux/kernel.h> | |||
#include <linux/init.h> | |||
#include <linux/stat.h> | |||
MODULE_LICENSE("GPL"); | |||
MODULE_AUTHOR("Peter Jay Salzman"); | |||
static short int myshort = 1; | |||
static int myint = 420; | |||
static long int mylong = 9999; | |||
static char *mystring = "blah"; | |||
static int myintArray[2] = { -1, -1 }; | |||
static int arr_argc = 0; | |||
/* | |||
* module_param(foo, int, 0000) | |||
* The first param is the parameters name | |||
* The second param is it's data type | |||
* The final argument is the permissions bits, | |||
* for exposing parameters in sysfs (if non-zero) at a later stage. | |||
*/ | |||
module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); | |||
MODULE_PARM_DESC(myshort, "A short integer"); | |||
module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | |||
MODULE_PARM_DESC(myint, "An integer"); | |||
module_param(mylong, long, S_IRUSR); | |||
MODULE_PARM_DESC(mylong, "A long integer"); | |||
module_param(mystring, charp, 0000); | |||
MODULE_PARM_DESC(mystring, "A character string"); | |||
/* | |||
* module_param_array(name, type, num, perm); | |||
* The first param is the parameter's (in this case the array's) name | |||
* The second param is the data type of the elements of the array | |||
* The third argument is a pointer to the variable that will store the number | |||
* of elements of the array initialized by the user at module loading time | |||
* The fourth argument is the permission bits | |||
*/ | |||
module_param_array(myintArray, int, &arr_argc, 0000); | |||
MODULE_PARM_DESC(myintArray, "An array of integers"); | |||
static int __init hello_5_init(void) | |||
{ | |||
int i; | |||
printk(KERN_INFO "Hello, world 5\n=============\n"); | |||
printk(KERN_INFO "myshort is a short integer: %hd\n", myshort); | |||
printk(KERN_INFO "myint is an integer: %d\n", myint); | |||
printk(KERN_INFO "mylong is a long integer: %ld\n", mylong); | |||
printk(KERN_INFO "mystring is a string: %s\n", mystring); | |||
for (i = 0; i < (sizeof myintArray / sizeof (int)); i++) | |||
{ | |||
printk(KERN_INFO "myintArray[%d] = %d\n", i, myintArray[i]); | |||
} | |||
printk(KERN_INFO "got %d arguments for myintArray.\n", arr_argc); | |||
return 0; | |||
} | |||
static void __exit hello_5_exit(void) | |||
{ | |||
printk(KERN_INFO "Goodbye, world 5\n"); | |||
} | |||
module_init(hello_5_init); | |||
module_exit(hello_5_exit); | |||
</pre> | |||
Raccomando di giocare con questo codice: | |||
<pre> | |||
satan# insmod hello-5.ko mystring="bebop" mybyte=255 myintArray=-1 | |||
mybyte is an 8 bit integer: 255 | |||
myshort is a short integer: 1 | |||
myint is an integer: 20 | |||
mylong is a long integer: 9999 | |||
mystring is a string: bebop | |||
myintArray is -1 and 420 | |||
satan# rmmod hello-5 | |||
Goodbye, world 5 | |||
satan# insmod hello-5.ko mystring="supercalifragilisticexpialidocious" \ | |||
> mybyte=256 myintArray=-1,-1 | |||
mybyte is an 8 bit integer: 0 | |||
myshort is a short integer: 1 | |||
myint is an integer: 20 | |||
mylong is a long integer: 9999 | |||
mystring is a string: supercalifragilisticexpialidocious | |||
myintArray is -1 and -1 | |||
satan# rmmod hello-5 | |||
Goodbye, world 5 | |||
satan# insmod hello-5.ko mylong=hello | |||
hello-5.o: invalid argument syntax for mylong: 'h' | |||
</pre> | |||
==Moduli divisi in piu file== | ==Moduli divisi in piu file== |
contributi