Linux驅動 簡單的Linux驅動基礎知識
一、簡述
記--Linux驅動學習筆記。
Linux驅動程序初始化硬件設備,並提供硬件控制接口給更上一層的應用調用。
例如使用QT應用程序控制一個LED燈,需要有一個驅動程序初始化LED燈,並準備好給其它應用程序的可調用接口,然後QT應用程序通過接口進行控制LED燈。
二、設備分類
一般分爲字符設備、塊設備、網絡設備。
字符設備:如串口,像操作文件一樣
塊設備:如U盤,像操作文件一樣
網絡設備:如網卡,使用socket相關函數進行操作
三、簡單驅動程序的編寫
就是.c源文件
3.1 引用相關的頭文件
#include <linux/init.h> //module_init(),module_exit()
#include <linux/module.h> //MODULE_LICENSE(), MODULE_AUTHOR()
3.2 需要編寫一個初始化/加載函數--init()函數和一個退出/卸載函數--exit()函數。
其中使用module_init(初始化函數)來指定初始化函數,使用module_exit(退出函數)來指定退出函數。
模塊加載時會調用初始化函數,模塊卸載時會調用退出函數。
3.3 添加模塊相關描述信息
MODULE_LICENSE("GPL"); 說明遵循GPL協議
MODULE_AUTHOR("Genven_Liang"); 說明作者信息
3.4 driverTest.c文件
#include <linux/init.h> //__init, __exit
#include <linux/module.h> //module_init(), module_exit(),MODULE_LICENSE(),MODULE_AUTHOR(),MODULE_DESCRIPTION()
MODULE_LICENSE("GPL"); //聲明協議
MODULE_AUTHOR("Genven_Liang"); //作者信息
MODULE_DESCRIPTION("test for linux driver."); //對本驅動程序的描述
//初始化函數 執行insmod時會調用該函數
static int __init hello_init(void)
{
printk("hello_init!\n");
return 0;
}
//退出函數 執行remod時會調用該函數
static void __exit hello_exit(void)
{
printk("hello_exit!\n");
}
module_init(hello_init);
module_exit(hello_exit);
四、驅動程序的編譯
4.1 編譯方式有:
1)內部編譯:將驅動程序源碼放在內核源碼目錄中進行編譯
2)外部編譯:將驅動程序源碼放在內核源碼目錄外進行編譯
3)靜態編譯:編譯進uImage中
4)動態編譯 (.ko文件,動態加載驅模塊)
4.2 編譯器:
x86等架構使用gcc即可,arm嵌入式設備需要使用相關交叉編譯工具鏈。
4.3 編寫Makefile文件進行編譯
KERN_DIR ?= /usr/src/linux-headers-$(shell uname -r)/ #內核源碼目錄/usr/src/linux-headers-$(shell uname -r)/
PWD := $(shell pwd)
obj-m := driverTest.o
all:
make -C $(KERN_DIR) M=$(PWD) modules
clean:
make -C $(KERN_DIR) M=$(PWD) clean
編譯:make
查看生成的.ko文件, modinfo xxx.ko
五、使用驅動程序
5.1 查看當前已經加載的驅動程序:lsmod
信息比較多的話,使用grep進行檢索過濾。lsmod | grep driverTest
5.2 加載驅動:insmod driverTest.ko
管理員運行
5.3 查看內核打印信息:demsg
5.4 卸載驅動:rmmod driverTest