當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 學(xué)習(xí)筆記 > 嵌入式學(xué)習(xí)筆記:什么叫驅(qū)動(dòng)模塊,這里告訴你
模塊:指令集合,獨(dú)立命名,能獨(dú)立完成某一功能,提供接口。
1 應(yīng)用程序和底層驅(qū)動(dòng)的區(qū)別
應(yīng)用程序驅(qū)動(dòng)
加載方式主動(dòng)加載被動(dòng)加載
運(yùn)行空間userkernel
權(quán)限低高
作用范圍影響局部影響全局
函數(shù)來(lái)源庫(kù)函數(shù)/系統(tǒng)接口內(nèi)核提供的函數(shù)
2 如何寫(xiě)一個(gè)模塊
#include
/* These are either module local, or the kernel's dummy ones. */
加載模塊調(diào)用的初始化函數(shù)
extern int init_module(void); 卸載模塊
extern void cleanup_module(void); 通過(guò)makefile編譯,擴(kuò)展名為.ko文件加載模塊使用命令
sudo insmod xxx.ko
需要使用root權(quán)限加載
查看模塊打印信息
dmesg | tail
查看模塊信息描述
modinfo xxx.ko
查看當(dāng)前系統(tǒng)中所有已加載的驅(qū)動(dòng)模塊
lsmod
卸載模塊命令
sudo rmmod xxx
通常情況下使用內(nèi)核提供的宏來(lái)加載和卸載模塊加載
/* Each module must use one module_init(). */
#define module_init(initfn) \
static inline initcall_t __inittest(void) \
{ return initfn; } \
int init_module(void) __attribute__((alias(#initfn)));
卸載
#define module_exit(exitfn)
static inline exitcall_t __exittest(void)
{ return exitfn; }
void cleanup_module(void)
__attribute__((alias(#exitfn)));
為模塊增加信息
MODULE_AUTHOR("shixh");
MODULE_DESCRIPTION("test moduel");
MODULE_ALIAS("17021");
MODULE_LICENSE("GPL"); ***** GPL通用許可授權(quán),一般
情況下載linux下的驅(qū)動(dòng)都符合這個(gè)授權(quán)標(biāo)準(zhǔn)。
MODULE_VERSION("1.0.0.0");
obj-m := hello.o 指的是目標(biāo)文件,通過(guò)hello.o編出hello.ko hello-objs = hello_init.o hello_exit.o 指的是編出hello.o需要
哪些文件
3 模塊傳參
通過(guò)宏來(lái)傳遞參數(shù)
#define module_param(name, type, perm)
\
module_param_named(name, name, type, perm)
* module_param - typesafe helper for a module/cmdline parameter
* @value: the variable to alter, and exposed parameter name. 變量名
* @type: the type of the parameter 變量類(lèi)型
* @perm: visibility in sysfs. 可見(jiàn)性(注意8進(jìn)制表示)
傳參類(lèi)型
* Standard types are:
* byte, short, ushort, int, uint, long, ulong
* charp: a character pointer
* bool: a bool, values 0/1, y/n, Y/N.
* invbool: the above, only sense-reversed (N = true).
例如
module_param(g_iTest, int, 0)
value : g_iTest, type : int, perm : 0 (0表示在文件系統(tǒng)中不可見(jiàn), 0644文件系統(tǒng)可見(jiàn),root權(quán)限可修改)
傳參:
sudo insmod hello.ko g_iTest=18 (注意等號(hào)兩邊不能有空
格)
參數(shù)查看路徑
/sys/moudles/xxxxxx/parameters xxx指的是模塊名
當(dāng)perm為0644時(shí)root權(quán)限可修改參數(shù),通常情況下不建議
修改
根據(jù)參數(shù)名生成一個(gè)普通文件,當(dāng)模塊卸載時(shí),模塊對(duì)應(yīng)的文件夾自動(dòng)刪除
注意:使用module_param傳遞字符串時(shí)注意是否越界,有點(diǎn)像
gets
傳字符串時(shí)使用
#define module_param_string(name, string, len, perm)
fgets
/**
* module_param_string - a char array parameter
* @name: the name of the parameter 變量名
* @string: the string variable 變量名
* @len: the maximum length of the string, incl. terminator buf最大長(zhǎng)度
* @perm: visibility in sysfs. 可見(jiàn)性
*
* This actually copies the string when it's set (unlike
type charp).
* @len is usually just sizeof(string).
*/
傳遞數(shù)組
#define module_param_array(name, type, nump, perm) /**
* module_param_array - a parameter which is an array of some type
* @name: the name of the array variable 數(shù)組名
* @type: the type, as per module_param() 類(lèi)型
* @nump: optional pointer filled in with the number written 傳遞給數(shù)組的元素個(gè)數(shù),需要傳遞一個(gè)指針
* @perm: visibility in sysfs 可見(jiàn)性
*
* 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.
*/
例如 sudo insmod hello.ko g_iArr=1,2,3 注意:數(shù)組方式傳參時(shí)以逗號(hào)分隔
4 導(dǎo)出符號(hào)
導(dǎo)出符號(hào)所使用的宏 : EXPORT_SYMBOL_GPL /
EXPORT_SYMBOL
查看全局符號(hào)表命令 sudo cat /proc/kallsyms
例如在hello模塊導(dǎo)出變量或函數(shù),在world模塊中使用導(dǎo)出的函數(shù)或變量
1 在hello模塊使用 EXPORT_SYMBOL_GPL 導(dǎo)出,編譯時(shí)會(huì)在Module.symvers文件中保存導(dǎo)出符號(hào)的地址
2 把Module.symvers文件拷貝到hehe模塊文件夾中,并編譯,注意:在world模塊中使用導(dǎo)出的函數(shù)或變量要使用extern聲明
注意Makefile中要使用不同的目標(biāo)名,因?yàn)樵谀K加載時(shí)不允許出現(xiàn)同名模塊