2.6. 向模块传递命令行参数

模块可以接受命令行参数,但不是使用您可能熟悉的argc/argv

要允许将参数传递给您的模块,请将用于接收命令行参数值的变量声明为全局变量,然后使用MODULE_PARM()宏(在linux/module.h中定义)来设置机制。在运行时,insmod 将使用给定的任何命令行参数填充变量,例如 ./insmod mymodule.o myvariable=5。为了清晰起见,变量声明和宏应放在模块的开头。示例代码应该能清楚地解释我承认糟糕的解释。

MODULE_PARM()宏接受 2 个参数:变量的名称及其类型。支持的变量类型为“b”:单字节,“h”:短整型,“i”:整型,“l”:长整型和“s”:字符串,整数类型可以像往常一样是有符号的或无符号的。字符串应声明为“char *”,insmod 将为其分配内存。您应该始终尝试为变量提供初始默认值。这是内核代码,您应该进行防御性编程。例如

    int myint = 3;
    char *mystr;

    MODULE_PARM(myint, "i");
    MODULE_PARM(mystr, "s");
	

也支持数组。MODULE_PARM 中类型前面的整数值将指示某个最大长度的数组。用“-”分隔的两个数字将给出值的最小和最大数量。例如,一个至少有 2 个且不超过 4 个值的短整型数组可以声明为

    int myshortArray[4];
    MODULE_PARM (myintArray, "3-9i");
	

一个好的用法是设置模块变量的默认值,例如端口或 IO 地址。如果变量包含默认值,则执行自动检测(在其他地方解释)。否则,保持当前值。稍后将对此进行说明。

最后,还有一个宏函数,MODULE_PARM_DESC(),用于记录模块可以接受的参数。它接受两个参数:变量名和一个描述该变量的自由格式字符串。

示例 2-7. hello-5.c

/*  hello-5.c - Demonstrates command line argument passing to a module.
 *
 *  Copyright (C) 2001 by Peter Jay Salzman
 *
 *  08/02/2006 - Updated by Rodrigo Rubira Branco <rodrigo@kernelhacking.com>
 */

/* Kernel Programming */
#define MODULE
#define LINUX
#define __KERNEL__

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter Jay Salzman");

// These global variables can be set with command line arguments when you insmod
// the module in. 
//
static u8             mybyte = 'A';
static unsigned short myshort = 1;
static int            myint = 20;
static long           mylong = 9999;
static char           *mystring = "blah";
static int            myintArray[2] = { 0, 420 };

/*  Now we're actually setting the mechanism up -- making the variables command
 *  line arguments rather than just a bunch of global variables.
 */
MODULE_PARM(mybyte, "b");
MODULE_PARM(myshort, "h");
MODULE_PARM(myint, "i");
MODULE_PARM(mylong, "l");
MODULE_PARM(mystring, "s");
MODULE_PARM(myintArray, "1-2i");

MODULE_PARM_DESC(mybyte, "This byte really does nothing at all.");
MODULE_PARM_DESC(myshort, "This short is *extremely* important.");
// You get the picture.  Always use a MODULE_PARM_DESC() for each MODULE_PARM().


static int __init hello_5_init(void)
{
   printk(KERN_ALERT "mybyte is an 8 bit integer: %i\n", mybyte);
   printk(KERN_ALERT "myshort is a short integer: %hi\n", myshort);
   printk(KERN_ALERT "myint is an integer: %i\n", myint);
   printk(KERN_ALERT "mylong is a long integer: %li\n", mylong);
   printk(KERN_ALERT "mystring is a string: %s\n", mystring);
   printk(KERN_ALERT "myintArray is %i and %i\n", myintArray[0], myintArray[1]);
   return 0;
}


static void __exit hello_5_exit(void)
{
   printk(KERN_ALERT "Goodbye, world 5\n");
}


module_init(hello_5_init);
module_exit(hello_5_exit);

我建议试用一下这段代码

    satan# insmod hello-5.o 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.o 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.o mylong=hello
    hello-5.o: invalid argument syntax for mylong: 'h'