向android中增加自定义的Linux内核启动参数
前言,android设备中常常需要添加自定义的内核配置,如imx51的primary_di定义 pmem定义等,这时需要使用__setup函数,下面的文章中详述了该过程。转:如何增加自定义的Linux内核启动参数在驱动开发的过程中,有时为了调试方便,需要给驱动传入参数。下面就简单说明,如何给驱动传递参数和驱动如何使用参数。驱动可以编译成模块,在需要时加载;也可以编译进内核,和内核一起加
前言,android设备中常常需要添加自定义的内核配置,如imx51的primary_di定义 pmem定义等,这时需要使用__setup函数,下面的文章中详述了该过程。
转:如何增加自定义的Linux内核启动参数
在驱动开发的过程中,有时为了调试方便,需要给驱动传入参数。下面就简单说明,如何给驱动传递参数和驱动如何使用参数。
驱动可以编译成模块,在需要时加载;也可以编译进内核,和内核一起加载。
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 intmax_loop;
module_param(max_loop, int,0);
intloop(void)
{
inti=0;
for(i=0;i<max_loop;i++)
printk(“Inloop!/n”);
return0;
}
使用方法:
#insmod test.ko max_loop=10
1.2驱动不是模块,编译进内核
这时,max_loop可以在内核启动时传入,驱动中实现时使用__setup宏。
__setup(str, fn)
str为传递参数时使用的字符串,fn是参数传递后对应的处理函数。
例如:
#ifndef MODULE
static int __initmax_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.3module_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 __initdo_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_early_paramàparse_early_optionsàdo_early_param
具体地说,首先,parse_early_param把传递给内核的命令行参数,复制到一个临时变量tmp_cmdline中,然后传递给parse_early_options处理如下:
void __initparse_early_param(void)
{
strlcpy(tmp_cmdline, boot_command_line,COMMAND_LINE_SIZE);
parse_early_options(tmp_cmdline);
}
parse_early_options调用parse_args,parse_args把类似“max_loop=10”之类传给内核的字符串分解为字符串”max_loop”和”10”,然后传递给parse_one,parse_one最后调用do_early_param。
do_early_param对param, val的处理上面已经说过了。
更多推荐
所有评论(0)