http://blog.csdn.net/adaptiver/article/details/6212417 2011 转自:http://blogold./u3/91522/showart_2042348.html 在驱动开发的过程中,有时为了调试方便,需要给驱动传入参数。下面就简单说明,如何给驱动传递参数和驱动如何使用参数。 驱动可以编译成模块,在需要时加载;也可以编译进内核,和内核一起加载。
1.1 驱动作为模块时的传递参数可以在驱动中定义如下的宏:(#include <linux/moduleparam.h>) module_param(name, type, perm) name是变量名;type是变量类型(bool,charp,int等);perm是访问许可值,当perm=0时,不会在sysfs系统中生成相应的sysfs入口项;perm=S_IRUGO为对任何人只读;S_IRUGO|S_IWUSR为允许root用户修改参数。 例如: static int max_loop; module_param(max_loop, int, 0); int loop(void) { int i=0; for(i=0;i<max_loop;i++) printk(“In loop!/n”); return 0; } 使用方法: #insmod test.ko max_loop=10
1.2 驱动不是模块,编译进内核这时,max_loop可以在内核启动时传入,驱动中实现时使用__setup宏。 __setup(str, fn) str为传递参数时使用的字符串,fn是参数传递后对应的处理函数。 例如: #ifndef MODULE static int __init max_loop_setup(char *str) { max_loop = simple_strtol(str, NULL, 0); return 1; } __setup("max_loop=", max_loop_setup); #endif 在x86的grub(/boot/grub/menu.lst)中使用方法: kernel /vmlinuz-2.6.30.5 ro root=/dev/sda1 max_loop=10 目前已有的内核启动参数可以在此文件查找:documentation/kernel-parameters.txt。
1.3 module_param和__setup实现概述module_param宏在头文件include/linux/moduleparam.h中定义,调用顺序如下: module_paramàmodule_param_namedà module_param_callà__module_param_call(MODULE_PARAM_PREFIX,…) 最后,把用此宏定义的参数放在__param段中:__section__ ("__param")。 __param段参数的读取,涉及到内核加载模块原理。在用户空间执行insmod命令来加载模块时,会调用glibc(或uClibc)库中的init_module系统调用,并把系统调用号传递给内核,内核根据此系统调用号,到硬件相关的一个系统调用表中找到此offset的函数并执行。
对于__setup宏,在头文件include/linux/init.h中定义,最后把用此宏定义的参数放到.init.setup段中。 .init.setup段的读取在do_early_param函数中,实现如下: static int __init do_early_param(char *param, char *val) { struct obs_kernel_param *p; for (p = __setup_start; p < __setup_end; p++) { //从.init.setup段开始处__setup_start读取 if ((p->early && strcmp(param, p->str) == 0) || (strcmp(param, "console") == 0 && strcmp(p->str, "earlycon") == 0) ) { if (p->setup_func(val) != 0) //调用__setup(str, fn)中指定的fn函数, val是从内核启动传入的参数值 printk(KERN_WARNING "Malformed early option '%s'/n", param); } } return 0; } 调用顺序是:start_kernelàparse_argsàparse_one->unkown_bootoption->obsolete_checksetup。 |
|