免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1139 | 回复: 0
打印 上一主题 下一主题

从命令行传递参数给内核模块 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-01-24 10:07 |只看该作者 |倒序浏览

模块也可以从命令行获取参数。但不是通过以前你习惯的argc/argv。
要传递参数给模块,首先将获取参数值的变量声明为全局变量。然后使用宏MODULE_PARM()(在头文件linux/module.h)。运行时,insmod将给变量赋予命令行的参数,如同
        ./insmod mymodule.o myvariable=5。为使代码清晰,变量的声明和宏都应该放在
        模块代码的开始部分。以下的代码范例也许将比我公认差劲的解说更好。
宏MODULE_PARM()需要两个参数,变量的名字和其类型。支持的类型有"
        b": 比特型,"h": 短整型, "i": 整数型,"
        l: 长整型和 "s": 字符串型,其中正数型既可为signed也可为unsigned。
        字符串类型应该声明为"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端口或IO内存是一个不错的作法。如果这些变量有缺省值,则可以进行自动设备检测,
        否则保持当前设置的值。我们将在后续章节解释清楚相关内容。在这里我只是演示如何向一个模块传递参数。
最后,还有这样一个宏,MODULE_PARM_DESC()被用来注解该模块可以接收的参数。该宏
        两个参数:变量名和一个格式自由的对该变量的描述。
Example 2-7. hello-5.c
/*
*  hello-5.c - Demonstrates command line argument passing to a module.
*/
#include
#include
#include
#include
#include
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";
/*
* 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");
static int __init hello_5_init(void)
{
        printk(KERN_ALERT "Hello, world 5\n=============\n");
        printk(KERN_ALERT "myshort is a short integer: %hd\n", myshort);
        printk(KERN_ALERT "myint is an integer: %d\n", myint);
        printk(KERN_ALERT "mylong is a long integer: %ld\n", mylong);
        printk(KERN_ALERT "mystring is a string: %s\n", mystring);
        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'
module_param(name, type, perm)是一个宏,向当前模块传入参数,对源码分析如下
在include\linux\moduleparam.h中
#define module_param(name, type, perm)                \
    module_param_named(name, name, type, perm)
#define module_param_named(name, value, type, perm)               \
    param_check_##type(name, &(value));                   \
    module_param_call(name, param_set_##type, param_get_##type, &value, perm); \
    __MODULE_PARM_TYPE(name, #type)
#define module_param_call(name, set, get, arg, perm)                  \
    __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm)
#define __module_param_call(prefix, name, set, get, arg, perm)        \
    /* Default value instead of permissions? */            \
    static int __param_perm_check_##name __attribute__((unused)) =    \
    BUILD_BUG_ON_ZERO((perm)  0777 || ((perm) & 2));    \
    static char __param_str_##name[] = prefix #name;        \
    static struct kernel_param const __param_##name            \
    __attribute_used__                        \
    __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
    = { __param_str_##name, perm, set, get, arg }
__attibute__ 是gcc的关键字,可参考
http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Variable-Attributes.html
__attibute__将参数编译到__param段中,
module_param是一步一步展开的,
上面几个宏在include\linux\moduleparam.h中的顺序刚好相反
module_param宏的类似函数调用的顺序
module_param->module_param_named->module_param_call->__module_param_call
展开的顺序正好相反
__module_param_call->module_param_call->module_param_named->module_param
type类型可以是byte,short,ushort,int,
uint,long,ulong,charp(注:字符指针),bool,invbool,
perm表示此参数在sysfs文件系统中所对应的文件节点的属性。
权限在include/linux/stat.h中有定义
比如:
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
当perm为0时,表示此参数不存在 sysfs文件系统下对应的文件节点。
模块被加载后,在/sys/module/ 目录下将出现以此模块名命名的目录。
测试一下,插入一个驱动模块mp.ko,
sudo insmod mp.ko
发现 /sys/module下出现mp这个文件夹
mp中有drivers/,sections/,parameters/,initstate,refcnt,srcversion
其中initstate 里面内容为:live
refcnt里面内容为:0
srcversion里面内容为:F9BDEBF706329B443C28E08,很长,应该是一个唯一数字
driver文件夹里面是空的
sections有__param,__versions
__param里面内容为0xd081e0a8
__versions里面内容为0xd081e100
parameters有count,info(注:自己定义的参数)
count里面的内容为1(注:输出次数)
info里面的内容为a site about linux driver.(注:输出内容)
如果此模块存在perm不为0的命令行参数,
在此模块的目录下将出现parameters目录,
包含一系列以参数名命名的文件节点,
这些文件的权限值等于perm,文件的内容为参数的值。
在/sys/module/mp/出现的参数,在module结构中的对应如下
struct module
{
    enum module_state state;
    /* Member of list of modules */
    struct list_head list;
    ......
    /* Sysfs stuff. */
    struct module_kobject mkobj;
    struct module_param_attrs *param_attrs;
    struct module_attribute *modinfo_attrs;
    const char *version;
    const char *srcversion;
    struct kobject *drivers_dir;
    /* Exported symbols */
    const struct kernel_symbol *syms;
    unsigned int num_syms;
    const unsigned long *crcs;
    ......
    /* Section attributes */
    struct module_sect_attrs *sect_attrs;
#endif
    ......
};
enum module_state
{
    MODULE_STATE_LIVE,
    MODULE_STATE_COMING,
    MODULE_STATE_GOING,
};
state对应/sys/module/mp/initstate
drivers_dir对应/sys/module/mp/driver文件夹
version对应/sys/module/mp/sections/__version
srcversion对应/sys/module/mp/srcversion
测试模块,源程序mp.c内容如下:
#include
#include              

static char *info= "a site about linux driver.";           
static int count= 1;   
static int mp= 0;      
   
module_param(mp,int,0);
module_param(count,int,S_IRUSR);     
module_param(info,charp,S_IRUSR);   

MODULE_AUTHOR("ioctrl");
MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)      
{
    int i;
    for(i=0;i
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/54524/showart_470321.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP