当前位置: > Linux编程 >

如何在加载模块时向模块传递参数值

时间:2014-12-04 19:50来源:linux.it.net.cn 作者:IT网
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. 源文件
 
[c-sharp] view plaincopy
  1. #include <linux/kernel.h>  
  2. #include <linux/types.h>  
  3. #include <linux/spinlock.h>  
  4. #include <linux/interrupt.h>  
  5. #include <linux/delay.h>  
  6. #include <linux/blkdev.h>  
  7. #include <linux/list.h>  
  8. #include <linux/timer.h>  
  9. #include <linux/version.h>  
  10. #include <linux/moduleparam.h>  
  11. #include <linux/device.h>  
  12. #include <linux/module.h>  
  13. #include <linux/string.h>  
  14. #include <linux/dma-mapping.h>  
  15. #include <asm/semaphore.h>  
  16. #include <asm/page.h>  
  17. typedef uint8_t bool_t;  
  18.  
  19. #define MORNING   0  
  20. #define AFTERNOON 1  
  21. #define EVENING   2  
  22. #define UNKNOWN   3  
  23.  
  24. #define FALSE 0  
  25. #define TRUE  1  
  26.  
  27. #define USER_NUM 3  
  28.   
  29. /******** module information ***************/  
  30. MODULE_AUTHOR("H3C Corporation");  
  31. MODULE_DESCRIPTION("Demo function");  
  32. MODULE_LICENSE("GPL");  
  33.   
  34.   
  35.   
  36. /******** module parameters ***************/  
  37. static uint uid = 0;  
  38. module_param(uid, uint, S_IRUGO);  
  39.   
  40. static uint period = MORNING;  
  41. module_param(period, uint, S_IRUGO|S_IWUSR);  
  42.   
  43.   
  44. /******** global parameters ***************/  
  45. char user_name[USER_NUM][20] = {{"wuwu"}, {"pikaqiu"}, {"lala"}};  
  46. uint prev_period = UNKNOWN;  
  47. bool_t demo_quit = FALSE;  
  48. struct completion com_demo;  
  49.   
  50.   
  51. int demo_thread(void* unuse)  
  52. {  
  53.     daemonize("demo_thread");  
  54.       
  55.     for(;;)  
  56.     {  
  57.         if(demo_quit)  
  58.         {  
  59.             break;  
  60.         }  
  61.   
  62.         if(prev_period != period)  
  63.         {  
  64.             if(MORNING == period)  
  65.             {  
  66.                 printk(KERN_EMERG "Good morning, %s/n", user_name[uid]);  
  67.             }  
  68.             else if(AFTERNOON == period)  
  69.             {  
  70.                 printk(KERN_EMERG "Good afternoon, %s/n", user_name[uid]);  
  71.   
  72.             }  
  73.             else if(EVENING == period)  
  74.             {  
  75.                 printk(KERN_EMERG "Good evening, %s/n", user_name[uid]);  
  76.             }  
  77.             else  
  78.             {  
  79.                 printk(KERN_EMERG "Parameter period is invalid! Please choose from follows:/n");  
  80.                 printk(KERN_EMERG "0: means morning/n");  
  81.                 printk(KERN_EMERG "1: means afternoon/n");  
  82.                 printk(KERN_EMERG "2: means evening/n");  
  83.                 printk(KERN_EMERG "/n");  
  84.             }  
  85.               
  86.             prev_period = period;  
  87.         }  
  88.   
  89.         msleep(10);  
  90.     }  
  91.   
  92.     complete_and_exit(&com_demo, 0);  
  93. }  
  94.   
  95.   
  96. static int __init demo_init(void)  
  97. {  
  98.     pid_t pid = 0;  
  99.     uint32_t i = 0;  
  100.   
  101.   
  102.     if(uid >= USER_NUM)  
  103.     {  
  104.         printk(KERN_EMERG "Parameter uid is invalid, please choose from follows:/n");  
  105.         for(i=0; i<USER_NUM; i++)  
  106.         {  
  107.             printk(KERN_EMERG "i: named %s/n", user_name[i]);  
  108.         }  
  109.         printk(KERN_EMERG "/n");  
  110.   
  111.         return -1;  
  112.     }  
  113.   
  114.     init_completion(&com_demo);  
  115.     pid = kernel_thread(demo_thread, NULL, CLONE_KERNEL);  
  116.     if(pid < 0)  
  117.     {  
  118.         printk(KERN_EMERG "demo thread create failed!/n");  
  119.         return -1;  
  120.     }  
  121.   
  122.     printk(KERN_EMERG "Welcome to the demo!/n");  
  123.     return 0;  
  124. }  
  125.   
  126. static void __exit demo_exit(void)  
  127. {  
  128.     demo_quit = TRUE;  
  129.     wait_for_completion(&com_demo);  
  130.     printk(KERN_EMERG "Byebye, %s/n", user_name[uid]);  
  131.     return;  
  132. }  
  133.   
  134. module_init(demo_init);  
  135. module_exit(demo_exit);  

 
4. 经验总结
1、根据对不同用户权限要求设置perm位;
2、对于只需在加载模块时传递参数值、而不希望用户看到该参数,建议将perm位置为0。
(责任编辑:IT)
------分隔线----------------------------