1. 程式人生 > >向android中增加自定義的Linux核心啟動引數

向android中增加自定義的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的處理上面已經說過了。