模塊:指令集合,獨立命名,能獨立完成某一功能,提供接口。
1 應用程序和底層驅動的區別
應用程序驅動
加載方式主動加載被動加載
運行空間userkernel
權限低高
作用范圍影響局部影響全局
函數來源庫函數/系統接口內核提供的函數
2 如何寫一個模塊
#include
/* These are either module local, or the kernel's dummy ones. */
加載模塊調用的初始化函數
extern int init_module(void); 卸載模塊
extern void cleanup_module(void); 通過makefile編譯,擴展名為.ko文件加載模塊使用命令
sudo insmod xxx.ko
需要使用root權限加載
查看模塊打印信息
dmesg | tail
查看模塊信息描述
modinfo xxx.ko
查看當前系統中所有已加載的驅動模塊
lsmod
卸載模塊命令
sudo rmmod xxx
通常情況下使用內核提供的宏來加載和卸載模塊加載
/* 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通用許可授權,一般
情況下載linux下的驅動都符合這個授權標準。
MODULE_VERSION("1.0.0.0");
obj-m := hello.o 指的是目標文件,通過hello.o編出hello.ko hello-objs = hello_init.o hello_exit.o 指的是編出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. 變量名
* @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表示在文件系統中不可見, 0644文件系統可見,root權限可修改)
傳參:
sudo insmod hello.ko g_iTest=18 (注意等號兩邊不能有空
格)
參數查看路徑
/sys/moudles/xxxxxx/parameters xxx指的是模塊名
當perm為0644時root權限可修改參數,通常情況下不建議
修改
根據參數名生成一個普通文件,當模塊卸載時,模塊對應的文件夾自動刪除
注意:使用module_param傳遞字符串時注意是否越界,有點像
gets
傳字符串時使用
#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最大長度
* @perm: visibility in sysfs. 可見性
*
* 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 傳遞給數組的元素個數,需要傳遞一個指針
* @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.
*/
例如 sudo insmod hello.ko g_iArr=1,2,3 注意:數組方式傳參時以逗號分隔
4 導出符號
導出符號所使用的宏 : EXPORT_SYMBOL_GPL /
EXPORT_SYMBOL
查看全局符號表命令 sudo cat /proc/kallsyms
例如在hello模塊導出變量或函數,在world模塊中使用導出的函數或變量
1 在hello模塊使用 EXPORT_SYMBOL_GPL 導出,編譯時會在Module.symvers文件中保存導出符號的地址
2 把Module.symvers文件拷貝到hehe模塊文件夾中,并編譯,注意:在world模塊中使用導出的函數或變量要使用extern聲明
注意Makefile中要使用不同的目標名,因為在模塊加載時不允許出現同名模塊