2.8. 模組引數
由於系統的不同,驅動程式需要的引數也許會發生變化。這包括裝置編號以及其它一些用來控制驅動程式操作方式的引數。例如,scsi介面卡的驅動程式經常要處理一些選項,這些選項用來控制標記命令佇列的使用,而整合裝置電路驅動程式允許使用者控制dma操作。如果驅動程式用來控制一些早期的硬體,也許需要明確告訴驅動程式硬體的io埠或者io記憶體位址的位置。為滿足這種需求,核心允許對驅動程式指定引數,而這些引數可以在載入驅動程式模組時改變。
這些引數的值可在執行insmod或modprobe命令載入模組時賦值,而modprobe可以從它的配置檔案中讀取引數值。這兩個命令可在命令列接受幾種引數型別的賦值。例如,新增兩個引數:乙個是整數值howmany,另乙個是字串who。可用下面的命令列來載入核心模組:
insmod hello.ko howmany=10 who="andyliu"
這個命令的效果會讓hello列印10次「hello,andyliu」。
在insmod改變模組引數之前,模組必須讓這些引數對insmod命令可見。引數必須使用module_param巨集來宣告,這個巨集在linux/moduleparam.h中定義。
#define module_param(name, type, perm) \
module_param_named(name, name, type, perm)
module_param需要三個引數:變數的名稱、型別以及用於sysfs入口項的訪問許可掩碼。這個巨集必須放在任何函式之外,通常是在原始檔的頭部。這樣,通過下面的**來宣告它的引數並使之對insmod可見。
static int howmany = 1;
static char *who = "andyliu";
module_param(howmany, int, s_irugo);
module_param(who, charp, s_irugo);
參見例項
#include
#include
#include
static int howmany = 1;
static char *who = "andyliu";
module_param(howmany, int, s_irugo);
module_param(who, charp, s_irugo);
static int __init mod_param_init(void)
return 0;
}static void __exit mod_param_exit(void)
module_init(mod_param_init);
module_exit(mod_param_exit);
module_license("dual bsd/gpl");
ifeq ($(kernelrelease),)
kerneldir ?= /lib/modules/$(shell uname -r)/build
pwd := $(shell pwd)
all:
$(make) -c $(kerneldir) m=$(pwd) modules
clean:
$(make) -c $(kerneldir) m=$(pwd) clean
else
obj-m := mod_param.o
endif
核心支援的模組引數型別如下:
bool
invbool
布林值(true或false),關聯的變數應該是int型別。invbool型別反轉其值,true值變成false,而false變成true。
charp
字元指標值。核心會為使用者提供的字串分配記憶體,並相應設定指標。
intlong
short
uint
ulong
ushort
具有不同長度的基本整數值。以u開頭的型別用於無符號值。
模組裝載器也支援陣列引數,在提供陣列值時用逗號劃分各陣列成員。要宣告陣列引數,需要使用下面的巨集:
/*** module_param_array - a parameter which is an array of some type
* @name: the name of the array variable
* @type: the type, as per module_param()
* @nump: optional pointer filled in with the number written
* @perm: visibility in sysfs
** input and output are as comma-separated values. commas inside values
* don't work properly (eg. an array of charp).
** array_size(@name) is used to determine the number of elements in the
* array, so the definition must be visible.
*/#define module_param_array(name, type, nump, perm) \
module_param_array_named(name, name, type, nump, perm)
其中,name是陣列的名稱(也就是引數的名稱),type是陣列元素的型別,nump是乙個整數變數,而perm是常見的許可訪問值。如果在裝載時設定陣列引數,則num會被設定為使用者提供的值的個數。模組裝載器會拒絕接受超過陣列大小的值。
參見例項:
#include
#include
#include
static int ages = ;// 預設值
static int nump;
module_param_array(ages, int, &nump, s_irugo);
static int __init mod_param_init(void)
return 0;
}static void __exit mod_param_exit(void)
module_init(mod_param_init);
module_exit(mod_param_exit);
module_license("dual bsd/gpl");
如果需要的型別不在上面列出的清單中,模組**中的鉤子可以讓我們來定義這些型別。請參考linux/moduleparam.h檔案。備註:所有的模組引數都應該給定乙個預設值;insmod只會在使用者明確設定了引數的值的情況下才會改變引數的值。模組可以根據預設值來判斷是否是乙個顯示指定的引數。
module_param中的最後乙個成員是訪問許可值,應使用linux/stat.h中存在的定義。
#define s_irwxugo (s_irwxu|s_irwxg|s_irwxo)
#define s_iallugo (s_isuid|s_isgid|s_isvtx|s_irwxugo)
#define s_irugo (s_irusr|s_irgrp|s_iroth)
#define s_iwugo (s_iwusr|s_iwgrp|s_iwoth)
#define s_ixugo (s_ixusr|s_ixgrp|s_ixoth)
這個值用來控制誰能夠訪問sysfs中對模組引數的表述。如果perm被設定為0,就不會有對應的sysfs入口項;否則,模組引數會在/sys/module中出現,並設定為給定的訪問許可。如果對引數使用s_irugo,則任何人可讀取該引數,但不能修改;注意,如果乙個引數通過sysfs而被修改,則如同模組修改了這個引數的值一樣,但是核心不會以任何方式通知模組。大多數情況下,不應該讓模組引數是可寫的,除非打算檢測這種修改並作出相應的動作。
Linux裝置驅動之第 2 章 預備知識
2.6.預備知識 核心是乙個特定的環境,對需要和它介面的 有自己的一些要求。大部分核心 中都要包含相當數量的標頭檔案,以便獲得函式 資料型別和變數的定義。有幾個標頭檔案是用於模組的,必須出現在每個可裝載的模組中。所有的模組 中都包含下面兩行 include include linux module....
Linux裝置驅動之第 2 章 核心符號表
2.5.核心符號表 insmod使用公共核心符號表來解析模組中未定義的符號。公共核心符號表包含所有的全域性核心項 函式和變數 的位址,這是實現模組化驅動程式所必需的。當模組被裝入核心後,這個模組匯出的任何符號都會變成核心符號表的一部分。通常情況下,模組只需實現自己的功能,而無需匯出任何符號。但是,如...
Linux裝置驅動 模組
模組檔案 在檔案系統中可以被直接插入到核心的檔案 模組三要素 模組載入函式 必須 當在檔案系統中使用insmod或者該模組在核心被執行的時候,自動執行該函式 函式方式 1 預設方式 int init module void 2 使用者自定義 int test init void module ini...