很多情況下,我們期望通過參數來控制我們的驅動的行為,比如由於系統的不同,而為了保證我們驅動有較好的移植性,我們有時候期望通過傳遞參數來控制我們驅動的行為,這樣不同的系統中,驅動可能有不同的行為控制。
為了滿足這種需求,內核允許對驅動程序指定參數,而這些參數可在加載驅動的過程中動態的改變
參數的來源主要有兩個
使用insmod/modprobe ./xxx.ko
時候在命令行後直接給出參數;
modprobe命令裝載模塊時可以從它的配置文件/etc/modprobe.conf
文件中讀取參數值
這個宏必須放在任何函數之外,通常實在源文件的頭部
對於如何向模塊傳遞參數,Linux kernel 提供了一個簡單的框架。其允許驅動程序聲明參數,並且用戶在系統啟動或模塊裝載時為參數指定相應值,在驅動程序裡,參數的用法如同全局變量。
使用下面的宏時需要包含頭文件
module_param(name, type, perm)
module_param_array(name, type, num_point, perm);
module_param_named(name_out, name_in, type, perm);
module_param_string(name, string, len, perm);
內核支持的模塊參數類型如下
關於數組類型怎麼傳遞,我們後面會談到
注意
如果我們需要的類型不在上面的清單中,模塊代碼中的鉤子可讓我們來指定這些類型。
具體的細節請參閱moduleparam.h文件。所有的模塊參數都應該給定一個默認值;
insmod只會在用戶明確設定了參數值的情況下才會改變參數的值,模塊可以根據默認值來判斷是否一個顯示給定的值
perm訪問權限與linux文件愛你訪問權限相同的方式管理,
如0644,或使用stat.h中的宏如S_IRUGO表示。
我們鼓勵使用stat.h中存在的定義。這個值用來控制誰能夠訪問sysfs中對模塊參數的表述。
如果制定0表示完全關閉在sysfs中相對應的項,否則的話,模塊參數會在/sys/module中出現,並設置為給定的訪問許可。
如果指定S_IRUGO,則任何人均可讀取該參數,但不能修改
如果指定S_IRUGO | S_IWUSR 則允許root修改該值
注意
如果一個參數通過sysfs而被修改,則如果模塊修改了這個參數的值一樣,但是內核不會以任何方式通知模塊,大多數情況下,我們不應該讓模塊參數是可寫的,除非我們打算檢測這種修改並做出相應的動作。
如果你只有ko文件卻沒有源碼,想知道模塊中到底有哪些模塊參數,不著急,只需要用
modinfo -p ${modulename}
就可以看到個究竟啦。
對於已經加載到內核裡的模塊,如果想改變這些模塊的模塊參數該咋辦呢?簡單,只需要輸入
echo -n ${value} > /sys/module/${modulename}/parameters/${param}
來修改即可。
在模塊裡面, 聲明一個變量(全局變量),用來接收用戶加載模塊時傳遞的參數
module_param(name, type, perm);
這些宏不會聲明變量,因此在使用宏之前,必須聲明變量,典型地用法如下:
static int value = 0;
module_param(value, int, 0644);
MODULE_PARM_DESC(value_int, "Get an value from user...\n");
使用
sudo insmod param.ko value=100
來進行加載
static char *string = "gatieme";
module_param(string, charp, 0644);
MODULE_PARM_DESC(string, "Get an string(char *) value from user...\n");
使用
sudo insmod param.ko string="hello"
前面那種情況下,外部參數的名字和模塊內部的名字必須一致,那麼有沒有其他的綁定方法,可以是我們的參數傳遞更加靈活呢?
使模塊源文件內部的變 量名與外部的參數名有不同的名字,通過module_param_named()定義。
module_param_named(name_out, name_in, type, perm);
使用
static int value_in = 0;
module_param_named(value_out, value_in, int, 0644);
MODULE_PARM_DESC(value_in, "value_in named var_out...\n");
加載
sudo insmod param.ko value_out=200
加載模塊的時候, 傳遞字符串到模塊的一個全局字符數組裡面
module_param_string(name, string, len, perm);
static char buffer[20] = "gatieme";
module_param_string(buffer, buffer, sizeof(buffer), 0644);
MODULE_PARM_DESC(value_charp, "Get an string buffer from user...\n");
加載模塊的時候, 傳遞參數到模塊的數組中
module_param_array(name, type, num_point, perm);
使用
static int array[3];
int num;
module_param_array(array, int, &num, 0644);
MODULE_PARM_DESC(array, "Get an array from user...\n");
#include
#include
#include
/*
* 在模塊裡面, 聲明一個變量(全局變量),
* 用來接收用戶加載模塊哦時傳遞的參數
*
* module_param(name, type, perm)
**/
static int value = 0;
module_param(value, int, 0644);
MODULE_PARM_DESC(value_int, "Get an value from user...\n");
/*
* 在模塊內部變量的名字和加載模塊時傳遞的參數名字不同
*
* module_param_named(name_out, name_in, type, perm)
*
* @name_out 加載模塊時,參數的名字
* @name_in 模塊內部變量的名字
* @type 參數類型
* @perm 訪問權限
* */
static int value_in = 0;
module_param_named(value_out, value_in, int, 0644);
MODULE_PARM_DESC(value_in, "value_in named var_out...\n");
/*
* 加載模塊的時候, 傳遞字符串到模塊的一個全局字符數組裡面
*
* module_param_string(name, string, len, perm)
*
* @name 在加載模塊時,參數的名字
* @string 模塊內部的字符數組的名字
* @len 模塊內部的字符數組的大小
* #perm 訪問權限
*
* */
static char *string = NULL;
module_param(string, charp, 0644);
MODULE_PARM_DESC(string, "Get an string(char *) value from user...\n");
static char buffer[20] = "gatieme";
module_param_string(buffer, buffer, sizeof(buffer), 0644);
MODULE_PARM_DESC(value_charp, "Get an string buffer from user...\n");
/*
* 加載模塊的時候, 傳遞參數到模塊的數組中
*
* module_param_array(name, type, num_point, perm)
*
* @name 模塊的數組名,也是外部制定的數組名
* @type 模塊數組的數據類型
* @num_point 用來獲取用戶在加載模塊時傳遞的參數個數,
* 為NULL時,表示不關心用戶傳遞的參數個數
* @perm 訪問權限
*
* */
static int array[3];
int num;
module_param_array(array, int, &num, 0644);
MODULE_PARM_DESC(array, "Get an array from user...\n");
int __init param_module_init(void)
{
int index = 0;
printk("\n---------------------\n");
printk("value : %d\n", value);
printk("value_in : %d\n", value_in);
printk("string : %s\n", string);
printk("buffer : %s\n", buffer);
for(index = 0; index < num; index++)
{
printk("array[%2d] : %d\n", index, array[index]);
}
printk("---------------------\n");
return 0;
}
void __exit param_module_exit(void)
{
printk("\n---------------------\n");
printk("exit param dobule\n");
printk("---------------------\n");
}
module_init(param_module_init);
module_exit(param_module_exit);
obj-m := param.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
sudo insmod param.ko value=100 value_out=200 string="gatieme" buffer="Hello-World" array=100,200,300
dmesg查看
sudo rmmod param
modinfo -p param.ko
首先查看一下sysfs目錄下的本模塊參數信息
ls /sys/module/param/parameters
動態修改