在應用層的C程序都是通過 main 函數的參數進行傳遞參數。
在驅動層則是使用模塊參數 進行參數傳遞。
由於最近項目需要用到,就學習記錄一下。
一、宏及參數介紹
1、模塊參數宏
模塊參數宏常用的有兩個, module_param 和 module_param_array。
定義在文件 kernel\include\linux\moduleparam.h 中。
(1)module_param
module_param(參數名,參數類型,參數讀/寫權限)
(1)module_param_array
module_param_array(參數名,參數類型,數組長度,參數讀/寫權限)
2、參數名
在模塊參數宏的第一個參數就是參數名,這個其實就是在驅動中定義個一個變量名,並且在傳入參數時也會用到(例如:參數名=xxx)。
該變量的類型要與參數類型一致。
3、參數類型
參數類型可以爲 byte 、 short 、 ushort 、 int 、 uint 、 long 、 ulong 、 charp (字符指針)、 booI
或 invbool (布爾的反),。
參數類型要與參數名的變量類型一致。
4、數組長度
這個參數指的是傳入的數組長度(不是定義的數組長度),是個變量,是個傳出參數。
應該定義一個int類型的變量,然後將該變量的指針傳入,這樣可以獲取到傳入的參數個數。
5、參數讀/寫權限
可選的權限宏:
- S_IRWXUGO:用戶、用戶組、其他組有 讀 寫 執行 權限。
- S_IRUGO:用戶、用戶組、其他組有 讀 權限。
- S_IWUGO:用戶、用戶組、其他組有 寫 權限。
- 0:該參數不生效。
二、參數傳遞
參數傳遞發生在裝載內核模塊的時候,有兩種情況,驅動模塊外置加載、驅動模塊內置加載。
1、驅動模塊外置加載
在通過命名 insmod 加載驅動時可以進行傳遞參數。
insmod test.ko param1=value1 param2=value2
然後傳入的參數會覆蓋原本在驅動中定義的參數變量的默認值。
2、驅動模塊內置加載
這種情況無法通過 insmod 加載驅動進行參數傳遞。
但是 bootloader 可以通過在 bootargs 裏進行參數配置給內核驅動傳遞參數。以 modename.paramname=value 的形式。
三、測試代碼
1、源碼
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
/*************************************************************************************************/
// 局部宏定義
/*************************************************************************************************/
#define EN_DEBUG 1 /* 調試信息開關 */
#if EN_DEBUG
#define PRINT(x...) printk(KERN_EMERG x) /* 提高打印等級 */
#else
#define PRINT(x...)
#endif
/*************************************************************************************************/
// 局部變量
/*************************************************************************************************/
static char *s_param_str = "str"; /* 字符串變量 */
static int s_param_int = 66; /* int變量 */
static int s_param_array[3] = {1,2,3}; /* int數組 */
static int s_param_array_len; /* int數組的長度 */
/**************************************************************************************************
** 函數名稱: drv_init
** 功能: 驅動初始化函數,在加載時被調用
** 參數: 無
** 返回: 無
**************************************************************************************************/
static int __init drv_init(void)
{
int i;
PRINT("[KERNEL]:%s ------ \n", __FUNCTION__);
PRINT("[KERNEL]:s_param_str = %s \n", s_param_str);
PRINT("[KERNEL]:s_param_int = %d \n", s_param_int);
PRINT("[KERNEL]:s_param_array_len = %d \n", s_param_array_len);
for (i = 0; i < 3; ++i) {
PRINT("[KERNEL]:s_param_array[%d] = %d\n", i, s_param_array[i]);
}
return 0;
}
/**************************************************************************************************
** 函數名稱: drv_exit
** 功能描述: 驅動退出函數,在卸載時被調用
** 參數: 無
** 返回: 無
**************************************************************************************************/
static void __exit drv_exit(void)
{
PRINT("[KERNEL]:%s ------ \n", __FUNCTION__);
}
/* 定義模塊參數 */
module_param(s_param_str, charp, S_IRUGO);
module_param(s_param_int, int, S_IRUGO);
module_param_array(s_param_array, int, &s_param_array_len, S_IRUGO);
module_init(drv_init); /* 模塊初始化 */
module_exit(drv_exit); /* 模塊卸載 */
MODULE_AUTHOR("hrx"); /* 模塊作者 */
MODULE_DESCRIPTION("Linux Driver"); /* 模塊描述 */
MODULE_VERSION("1.0.0"); /* 模塊版本 */
MODULE_LICENSE("GPL"); /* 模塊遵守的License */
2、測試
(1)不傳入參數
不傳入參數則使用默認定義變量時的初試參數。
t@imx6qsabresd:/tmp# insmod param_demo.ko
[ 8294.829669] [KERNEL]:drv_init ------
[ 8294.833347] [KERNEL]:s_param_str = str
[ 8294.837271] [KERNEL]:s_param_int = 66
[ 8294.841028] [KERNEL]:s_param_array_len = 0
[ 8294.845262] [KERNEL]:s_param_array[0] = 1
[ 8294.849282] [KERNEL]:s_param_array[1] = 2
[ 8294.853297] [KERNEL]:s_param_array[2] = 3
(2)傳入字符串及數字
root@imx6qsabresd:/tmp# insmod param_demo.ko s_param_str="newstr" s_param_int=88
[ 8365.399765] [KERNEL]:drv_init ------ o.ko s_param_str="newstr" s_param_int=88
[ 8365.403443] [KERNEL]:s_param_str = newstr
[ 8365.407620] [KERNEL]:s_param_int = 88
[ 8365.411380] [KERNEL]:s_param_array_len = 0
[ 8365.415615] [KERNEL]:s_param_array[0] = 1
[ 8365.419633] [KERNEL]:s_param_array[1] = 2
[ 8365.423681] [KERNEL]:s_param_array[2] = 3
可以發現變量 s_param_str 和 s_param_int 被改變了。
(2)傳入字符串及數字
root@imx6qsabresd:/tmp# insmod param_demo.ko s_param_array=999,888,777
[ 8445.969720] [KERNEL]:drv_init ------
[ 8445.973398] [KERNEL]:s_param_str = str
[ 8445.977329] [KERNEL]:s_param_int = 66
[ 8445.981088] [KERNEL]:s_param_array_len = 3
[ 8445.985321] [KERNEL]:s_param_array[0] = 999
[ 8445.989515] [KERNEL]:s_param_array[1] = 888
[ 8445.993736] [KERNEL]:s_param_array[2] = 777
可以看到定義的數組內容發生了改變,數組長度變量被修改爲3。
假如輸入的參數長度大於定義的數組變量長度則會崩潰,驅動模塊會加載失敗。
root@imx6qsabresd:/tmp# insmod param_demo.ko s_param_array=999,888,777,888
[ 8550.298418] s_param_array: can only take 3 arguments
[ 8550.303397] param_demo: `999' invalid for parameter `s_param_array'
insmod: can't insert 'param_demo.ko': Invalid argument