Linux驅動之模塊參數——學習筆記(6)

在應用層的C程序都是通過 main 函數的參數進行傳遞參數。
在驅動層則是使用模塊參數 進行參數傳遞。
由於最近項目需要用到,就學習記錄一下。


一、宏及參數介紹

1、模塊參數宏

模塊參數宏常用的有兩個, module_parammodule_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_strs_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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章