Linux 驅動之模組參數--Linux裝置驅動程式
模組參數
很多情況下,我們期望通過參數來控制我們的驅動的行為,比如由於系統的不同,而為了保證我們驅動有較好的移植性,我們有時候期望通過傳遞參數來控制我們驅動的行為,這樣不同的系統中,驅動可能有不同的行為控制。
為了滿足這種需求,核心允許對驅動程式指定參數,而這些參數可在載入驅動的過程中動態改變
參數的來源主要有兩個
使用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);
參數類型
核心支援的模組參數類型如下
| 參數 |
描述 |
| bool |
布爾類型(true/false),關聯的變數類型應該死int |
| intvbool |
bool的反值,例如賦值位true,但是實際值位false |
| int |
整型 |
| long |
長整型 |
| short |
短整型 |
| uint |
無符號整型 |
| ulong |
無符號長整形型 |
| ushort |
無符號短整型 |
| charp |
字元指標類型,核心會為使用者提供的字串分配記憶體,並設定相應指標 |
關於數群組類型怎麼傳遞,我們後面會談到
注意
如果我們需要的類型不在上面的清單中,模組代碼中的鉤子可讓我們來指定這些類型。
具體的細節請參閱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);
| 參數 |
描述 |
| name |
用來接收參數的變數名 |
| type |
參數的資料類型 |
| perm |
用於sysfs入口項系的訪問可見度掩碼 |
樣本–傳遞int
這些宏不會聲明變數,因此在使用宏之前,必須聲明變數,典型地用法如下:
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
來進行載入
樣本–傳遞charp
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"
在模組內部變數的名字和載入模組時傳遞的參數名字不同
前面那種情況下,外部參數的名字和模組內部的名字必須一致,那麼有沒有其他的Binder 方法,可以是我們的參數傳遞更加靈活呢?
使模組源檔案內部的變 量名與外部的參數名有不同的名字,通過module_param_named()定義。
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");
載入
sudo insmod param.ko value_out=200
傳遞字串
載入模組的時候, 傳遞字串到模組的一個全域字元數組裡面
module_param_string(name, string, len, perm);
| 參數 |
描述 |
| 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);
| 參數 |
描述 |
| 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");
param驅動源碼驅動源碼param.c
#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);
Makefile
obj-m := param.oKERNELDIR ?= /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)all: make -C $(KERNELDIR) M=$(PWD) modulesclean: 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查看參數
modinfo -p param.ko
動態修改模組參數
首先查看一下sysfs目錄下的本模組參數資訊
ls /sys/module/param/parameters
動態修改