
一、簡介
在嵌入式linux應用開發中,可以給main()函數傳遞參數,這樣應用程序就能知道最初的控制參數是什么,當然也可以選擇不向應用程序傳遞參數。在驅動開發中,會使用到insmod命令來加載一個驅動模塊,這時候我們也可以使用insmod命令向驅動模塊傳遞參數。
使用模塊的參數傳遞機制,對調試系統非常方便!
【資料圖】
二、參數傳遞方式
參數傳遞分為兩種:
內置模塊參數傳遞:即將模塊編譯構建進內核鏡像。
外置模塊參數傳遞:使用insmod等命令裝在的內核模塊。
對于內置模塊參數傳遞,一般在bootloader中可向內置的模塊傳遞參數,例如可以在bootargs中設置模塊名.參數名=值的形式給該內置的模塊傳遞參數;對于外置模塊,在裝載內核模塊時,我們可以向模塊傳遞參數,形式為:
insmode(或modprobe)模塊名參數名=參數值
如果不傳遞參數,參數將使用模塊內定義的缺省值。
三、技術點
1、變量權限
向驅動模塊傳遞參數,必須事先在驅動源碼中聲明某一個變量可作為模塊參數傳遞,并且指定變量的權限,常見的權限參數如下:
宏定義 | 權限解釋 |
---|---|
#defineS_IRUSR 00400 | 文件所有者可讀 |
#defineS_IWUSR 00200 | 文件所有者可寫 |
#defineS_IXUSR 00100 | 文件所有者可執行 |
#defineS_IRGRP 00040 | 與文件所有者同組的用戶可讀 |
#defineS_IWGRP 00020 | |
#defineS_IXGRP 00010 | |
#defineS_IROTH 00004 | 與文件所有者不同組的用戶可讀 |
#defineS_IWOTH 00002 | |
#defineS_IXOTH 00001 |
上述宏定義中,S_I是公共的寫法,R = read,W = write,X = execute , USR = user,GPR = group。
當然,也可以這樣看:可以將數字最后三位轉化為二進制:xxx xxx xxx,高位往低位依次看,第一位為 1 表示文件所有者可讀,第二位為 1 表示文件所有者可寫,第三位為 1 表示文件所有者可執行;接下來三位表示文件所有者同組成員的權限;再下來三位為不同組用戶權限。
使用"|"(或操作),可以一次設置多個權限。
了解了一個變量有哪些常見的權限可供設置,接下來看看如何將一個變量聲明為可傳遞參數的變量。
2、傳遞普通的參數
傳遞普通的參數(例如 bool、char、int),使用下列宏定義:
module_param(name,type,perm);
name:要傳遞進去參數的名稱。
type:要傳遞進去參數的類型。
perm:要傳遞進去參數的讀寫權限。
module_param()宏在/sys/module下創建子目錄。上述代碼,將在/sys/module/中可查看對應的參數:
3、傳遞數組
傳遞數組參數使用下列的宏定義:
module_param_array(name,type,nump,perm)
name:要傳遞進去參數的名稱。
type:要傳遞進去參數的類型。
nump:實際傳入進去參數的個數。
perm:要傳遞進去參數的讀寫權限。
4、參數改變時回調
我們已經知道,可以向/sys/module/下的參數名稱寫入參數,這意味將改變參數的值,如果使用module_param()和module_param_array(),則無法獲知參數的值是否改變,如果我們想要讓系統獲知參數的改變,并根據參數改變進一步執行處理,則需要使用module_param_cb()注冊參數值改變時的處理函數。在內核中,module_param_cb()宏用于注冊回調,每當參數(形參)發生變化時,將調用此回調函數:
module_param_cb(name,ops,arg,perm)
name:要傳遞進去參數的名稱。
ops:該參數的set和get操作。
arg:傳遞給ops中回到函數的參數。
perm:要傳遞進去參數的讀寫權限。
四、代碼實驗
例如下列代碼:
/************************************************************************************@Copyright:IriczhaoCo.,Ltd.2021-2029.Allrightsreserved.*@File:dt_param_trans_demo.c*@Descripttion:linuxkernelmoduleparameterpassingexperiment*@version:1.0*@Author:iriczhao*@Date:2023-08-71506*@LastEditors:iriczhao************************************************************************************/#include#include#include#includeintvalue,arr_value[4];char*name;intcb_value=0;//聲明模塊參數module_param(value,int,S_IRUSR|S_IWUSR);//integer類型module_param(name,charp,S_IRUSR|S_IWUSR);//String類型module_param_array(arr_value,int,NULL,S_IRUSR|S_IWUSR);//整型數組/*----------------------Module_param_cb()--------------------------------*/intnotify_param(constchar*val,conststructkernel_param*kp){intres=param_set_int(val,kp);//Usehelperforwritevariableif(res==0){printk(KERN_INFO"Callbackfunctioncalled...");printk(KERN_INFO"Newvalueofcb_value=%d",cb_value);return0;}return-1;}conststructkernel_param_opsmy_param_ops={.set=notify_param,.get=param_get_int,};module_param_cb(cb_value,&my_param_ops,&cb_value,S_IRUGO|S_IWUSR);staticint__initdt_param_trans_demo_init(void){inti;//打印出模塊參數printk(KERN_INFO"Value=%d",value);printk(KERN_INFO"cb_value=%d",cb_value);printk(KERN_INFO"Name=%s",name);for(i=0;i<(sizeofarr_value/sizeof(int));i++){printk(KERN_INFO"Arr_value[%d]=%d",i,arr_value[i]);}printk(KERN_INFO"KernelModuleInsertedSuccessfully...");return0;}staticvoid__exitdt_param_trans_demo_exit(void){printk(KERN_INFO"KernelModuleRemovedSuccessfully...");}module_init(dt_param_trans_demo_init);module_exit(dt_param_trans_demo_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("iriczhao");MODULE_DESCRIPTION("linuxkernelmoduleparameterpassingexperiment");MODULE_VERSION("1.0");
將上述代碼以模塊方式構建,然后將生成的dt_param_trans_demo.ko模塊載入內核,在加載該模塊時,傳入value、name、arr_value的參數值,在程序中將會打印出輸出的參數值:
從上述輸出的結果中,cb_value的參數值為0(默認參數值),然后我們通過向/sys/module/dt_param_trans_demo/parameters/cb_value文件寫入參數值,這時候將會觸發該參數改變時綁定的回調函數,并打印出修改過后的參數值:
在載入一個模塊后,我們可以在/sys/module/模塊名/parameters/目錄下查看該模塊包含導出了哪些動態參數(參數以文件名稱表示),以及對應參數的權限(文件的權限對應參數的權限),例如本例中,將在/sys/module/dt_param_trans_demo/parameters/目錄下查看:
五、總結
1、模塊在載入的時候可以傳遞參數給模塊,前提是在模塊中提前聲明需要傳遞的參數。
2、當在系統啟動后,在/sys/module/模塊名/parameters/目錄中可以查看對應模塊下導出了哪些參數。也可以通過該目錄下的文件向對應的參數傳遞信新的參數值。
審核編輯:湯梓紅
標簽: