LKMPG: Ciao Mondo: differenze tra le versioni

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==
43

contributi