http://blog.csdn.net/adaptiver/article/details/6212417
2011
轉(zhuǎn)自:http://blogold.chinaunix.net/u3/91522/showart_2042348.html
在驅(qū)動開發(fā)的過程中,有時為了調(diào)試方便,需要給驅(qū)動傳入?yún)?shù)。下面就簡單說明,如何給驅(qū)動傳遞參數(shù)和驅(qū)動如何使用參數(shù)。
驅(qū)動可以編譯成模塊,在需要時加載;也可以編譯進內(nèi)核,和內(nèi)核一起加載。
可以在驅(qū)動中定義如下的宏:(#include <linux/moduleparam.h>)
module_param(name, type, perm)
name是變量名;type是變量類型(bool,charp,int等);perm是訪問許可值,當perm=0時,不會在sysfs系統(tǒng)中生成相應(yīng)的sysfs入口項;perm=S_IRUGO為對任何人只讀;S_IRUGO|S_IWUSR為允許root用戶修改參數(shù)。
例如:
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
這時,max_loop可以在內(nèi)核啟動時傳入,驅(qū)動中實現(xiàn)時使用__setup宏。
__setup(str, fn)
str為傳遞參數(shù)時使用的字符串,fn是參數(shù)傳遞后對應(yīng)的處理函數(shù)。
例如:
#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
目前已有的內(nèi)核啟動參數(shù)可以在此文件查找:documentation/kernel-parameters.txt。
module_param宏在頭文件include/linux/moduleparam.h中定義,調(diào)用順序如下:
module_paramàmodule_param_namedà module_param_callà__module_param_call(MODULE_PARAM_PREFIX,…)
最后,把用此宏定義的參數(shù)放在__param段中:__section__ ("__param")。
__param段參數(shù)的讀取,涉及到內(nèi)核加載模塊原理。在用戶空間執(zhí)行insmod命令來加載模塊時,會調(diào)用glibc(或uClibc)庫中的init_module系統(tǒng)調(diào)用,并把系統(tǒng)調(diào)用號傳遞給內(nèi)核,內(nèi)核根據(jù)此系統(tǒng)調(diào)用號,到硬件相關(guān)的一個系統(tǒng)調(diào)用表中找到此offset的函數(shù)并執(zhí)行。
對于__setup宏,在頭文件include/linux/init.h中定義,最后把用此宏定義的參數(shù)放到.init.setup段中。
.init.setup段的讀取在do_early_param函數(shù)中,實現(xiàn)如下:
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)
//調(diào)用__setup(str, fn)中指定的fn函數(shù), val是從內(nèi)核啟動傳入的參數(shù)值
printk(KERN_WARNING
"Malformed early option '%s'/n", param);
}
}
return 0;
}
調(diào)用順序是:start_kernelàparse_argsàparse_one->unkown_bootoption->obsolete_checksetup。