如何在加载模块时向模块传递参数值
的有关信息介绍如下:
1. 现象描述 Linux系统中,动态加载的模块往往需要实现: 1)在加载模块时,向模块传递一个参数值,且该参数值在模块运行过程中不能对其进行修改; 2)在加载模块时,向模块传递一个参数值,且该参数值在模块运行过程中根据需求对其进行动态修改。 2. 关键过程 1、Linux系统2.6内核下,可以通过宏module_param(name, type, perm)将参数name声明为模块参数,该参数值可以在加载模块时指定,否则为模块内定义的缺省值; 2、我们需要关注perm,perm表示此参数在sysfs文件系统中所对应的文件节点的属性: 1)当perm为0时,表示此参数不存在在sysfs文件系统下对应的文件节点; 2)模块被加载后,在/sys/module/目录下将出现以此模块名命名的目录; 3)如果此模块存在perm不为0的命令行参数,在此模块的目录下将出现parameters目录,包含一系列以参数命名的文件节点; 4)这些文件的权限值等于perm,文件的内容为参数的值。 3、perm有四种不同属性的模块参数: 1)可读写参数:此参数可以实时查看和动态修改其值;其属性为S_IRUGO|S_IWUSR; 2)可读参数:此参数只能实时查看,不能动态修改;其属性为S_IRUGO; 3)可写参数:此参数不能实时查看,但可以动态修改;其属性为S_IWUSR; 4)不可读写参数:此参数不能在sysfs文件系统中显示,也不能实时查看和动态修改其值;其属性值为0; 由此我们可以通过设置不同的perm值,实现不同参数不同的控制。 3. 案例实现 3.1. Demo说明 1、demo程序定义了2各模块参数,分别为uid、period。加载模块时,可以向模块传递这两个参数的值,否则这两个参数值将为默认值;模块运行过程中,两者均可被用户、用户所在组及其他组读取,后者还可被用户修改。 2、demo程序使用到的perm权限值含义: S_IRUGO:S_IRUSR|S_IRGRP|S_IROTH,表示可以被用户、用户所在组及其他组读取且只读; S_IWUSR:表示可以被用户(能动态加载模块的用户必须是超级用户)修改。 3、demo程序根据uid和period打印不同的信息;当period值变化时,会再次打印信息。 4、demo程序使用说明如下: 1)加载模块时:insmod demo.ko uid=0 period =0 2)模块运行过程中,读取uid值:cat /sys/module/demo/parameters/uid 3) 模块运行过程中,修改period值:echo 1 > /sys/module/demo/parameters/period 3.2. 源文件 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef uint8_t bool_t; #define MORNING 0 #define AFTERNOON 1 #define EVENING 2 #define UNKNOWN 3 #define FALSE 0 #define TRUE 1 #define USER_NUM 3 /******** module information ***************/ MODULE_AUTHOR("H3C Corporation"); MODULE_DESCRIPTION("Demo function"); MODULE_LICENSE("GPL"); /******** module parameters ***************/ static uint uid = 0; module_param(uid, uint, S_IRUGO); static uint period = MORNING; module_param(period, uint, S_IRUGO|S_IWUSR); /******** global parameters ***************/ char user_name[USER_NUM][20] = {{"wuwu"}, {"pikaqiu"}, {"lala"}}; uint prev_period = UNKNOWN; bool_t demo_quit = FALSE; struct completion com_demo; int demo_thread(void* unuse) { daemonize("demo_thread"); for(;;) { if(demo_quit) { break; } if(prev_period != period) { if(MORNING == period) { printk(KERN_EMERG "Good morning, %s/n", user_name[uid]); } else if(AFTERNOON == period) { printk(KERN_EMERG "Good afternoon, %s/n", user_name[uid]); } else if(EVENING == period) { printk(KERN_EMERG "Good evening, %s/n", user_name[uid]); } else { printk(KERN_EMERG "Parameter period is invalid! Please choose from follows:/n"); printk(KERN_EMERG "0: means morning/n"); printk(KERN_EMERG "1: means afternoon/n"); printk(KERN_EMERG "2: means evening/n"); printk(KERN_EMERG "/n"); } prev_period = period; } msleep(10); } complete_and_exit(&com_demo, 0); } static int __init demo_init(void) { pid_t pid = 0; uint32_t i = 0; if(uid >= USER_NUM) { printk(KERN_EMERG "Parameter uid is invalid, please choose from follows:/n"); for(i=0; i