嵌入式學習(xi)筆記:什(shen)么叫驅動模塊(kuai),這里告訴你
時間:2018-09-27 來源(yuan):未知
模塊:指令集合,獨立(li)命名,能(neng)獨立(li)完(wan)成某一功能(neng),提供接口。
1 應用(yong)程(cheng)序和底層驅動的區別
應用程序驅動
加載方式主動加載被動加載
運行空間userkernel
權限低高
作(zuo)用范圍(wei)影(ying)響局(ju)部影(ying)響全局(ju)
函(han)(han)數來(lai)源(yuan)庫函(han)(han)數/系統接口內核提供的函(han)(han)數
2 如何寫一個模塊
#include
/* These are either module local, or the kernel's dummy ones. */
加載模塊調(diao)用的初始(shi)化函數
extern int init_module(void); 卸載模(mo)塊(kuai)
extern void cleanup_module(void); 通過makefile編譯,擴展名為.ko文件加載模塊使用(yong)命令
sudo insmod xxx.ko
需要(yao)使(shi)用root權限加載
查看模塊打印信息
dmesg | tail
查看模塊信(xin)息描述
modinfo xxx.ko
查(cha)看當前系統(tong)中所有(you)已加載的驅動模塊
lsmod
卸載模塊命(ming)令(ling)
sudo rmmod xxx
通常情況下使(shi)用內核提供(gong)的宏來(lai)加(jia)(jia)載(zai)和(he)卸載(zai)模塊加(jia)(jia)載(zai)
/* 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通用許可(ke)授(shou)權,一般
情況(kuang)下載linux下的驅動都符(fu)合這個(ge)授權(quan)標(biao)準。
MODULE_VERSION("1.0.0.0");
obj-m := hello.o 指的是目標文件,通(tong)過hello.o編出(chu)hello.ko hello-objs = hello_init.o hello_exit.o 指的是編出(chu)hello.o需要
哪些文件
3 模塊傳參
通過宏來傳遞參數
#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. 變量名(ming)
* @type: the type of the parameter 變量類型
* @perm: visibility in sysfs. 可見性(注意8進制表示)
傳參類型
* 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表示在文(wen)件(jian)系統中(zhong)不可見(jian), 0644文(wen)件(jian)系統可見(jian),root權限(xian)可修改(gai))
傳參:
sudo insmod hello.ko g_iTest=18 (注意等號兩邊不能有空
格)
參數查看路徑
/sys/moudles/xxxxxx/parameters xxx指的是(shi)模塊名
當perm為0644時root權(quan)限可(ke)修(xiu)改參數,通常情況下不建議
修改
根據參數名(ming)生成(cheng)一個普通文(wen)件(jian),當模塊卸載時(shi),模塊對(dui)應的(de)文(wen)件(jian)夾自動刪除
注意(yi):使用module_param傳遞字符串時注意(yi)是否越界,有點像(xiang)
gets
傳字符串時(shi)使用
#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 變量(liang)名
* @len: the maximum length of the string, incl. terminator buf最大(da)長度
* @perm: visibility in sysfs. 可(ke)見性(xing)
*
* This actually copies the string when it's set (unlike
type charp).
* @len is usually just sizeof(string).
*/
傳遞數組
#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 數組名
* @type: the type, as per module_param() 類型
* @nump: optional pointer filled in with the number written 傳遞(di)給數(shu)組的元(yuan)素個數(shu),需要傳遞(di)一個指針
* @perm: visibility in sysfs 可見(jian)性(xing)
*
* 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 注意:數組(zu)方式傳參時以逗號分(fen)隔
4 導出符號
導出符號所使用的宏 : EXPORT_SYMBOL_GPL /
EXPORT_SYMBOL
查看全局符(fu)號表命(ming)令(ling) sudo cat /proc/kallsyms
例如在(zai)hello模塊(kuai)(kuai)導(dao)出(chu)變量或(huo)函數,在(zai)world模塊(kuai)(kuai)中(zhong)使用導(dao)出(chu)的函數或(huo)變量
1 在hello模塊使用 EXPORT_SYMBOL_GPL 導出,編譯時(shi)會(hui)在Module.symvers文件中(zhong)保存導出符號的地址
2 把Module.symvers文件(jian)拷(kao)貝到hehe模(mo)塊文件(jian)夾(jia)中(zhong),并(bing)編譯(yi),注意:在world模(mo)塊中(zhong)使用(yong)導(dao)出的(de)函數(shu)或變量要(yao)使用(yong)extern聲明
注意Makefile中要使用不同(tong)的(de)目(mu)標名,因為在模塊加載(zai)時不允許出現同(tong)名模塊