【迅為iTop4412學習筆記】6. 驅動註冊
宣告
以下都是我剛開始看驅動視訊的個人強行解讀,如果有誤請指出,共同進步。
本節目標
驅動註冊
上一篇我們註冊了裝置,接下來就是要註冊驅動,而註冊完驅動,就可以基佬配對了…
首先我們開啟標頭檔案,看一下驅動註冊的結構體長啥樣
vim include/linux/platform_device.h
開啟看到的就是上一節用到的註冊裝置的結構體,然而本節是註冊驅動,所以我們搜尋platform_driver並檢視
struct platform_driver {
int (*probe) (struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
extern int platform_driver_register(struct platform_driver *);
extern void platform_driver_unregister(struct platform_driver *);
對於驅動,有幾種常見狀態:初始化、移除、休眠、復位,所以結構體內定義了很多的函式(英文翻譯很直白了…)
我們註冊了裝置,也註冊了驅動,那麼linux會呼叫platform_match進行匹配,匹配完成之後會呼叫probe函式進行初始化,這些下面配置結構體再說。
除了結構體,還發現下面有兩行,看名字就能看出來是註冊和解除安裝驅動的函式,也很直白了…
裝置和驅動結構體的name和id已經說過一萬遍要匹配了,但是你有沒有發現,驅動結構體裡的name和id哪兒去了?其實在此結構體內還定義了一個結構體叫struct device_driver driver;而這個結構體在標頭檔案 include/linux/device.h 內,有興趣可以開啟看一下結構體內定義了那些成員,我們暫時用到的只有name, 除此之外還要配置一個引數 owner,一般賦值為THIS_MODULE,我想應該是涉及到許可權吧。
下面開始註冊驅動
1. 我們先寫一個驅動出來
首先我們先寫一個類似第一節最簡linux驅動那樣的驅動出來
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("MrYang");
static int mryang_init(void)
{
printk(KERN_EMERG "HELLO MrYang\n");
return 0;
}
static void mryang_exit(void)
{
printk(KERN_EMERG "Bye MrYang\n");
}
module_init(mryang_init);
module_exit(mryang_exit);
2.編寫註冊驅動用到的結構體
上面只是一個驅動,我們要註冊,就要用到驅動的結構體,用註冊、解除安裝的函式來給linux傳參,這些都在標頭檔案裡,所以我們要在驅動的那個檔案裡包含標頭檔案:
#include <linux/platform_device.h>
接下來就是定義驅動的結構體:
上面我們查看了linux是如何定義驅動的結構體,裡面有probe,remove函式等等,我們只是學習+體驗,所以只需要先編寫載入和解除安裝兩個結構體成員函式就可以了。
// 原型
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
// 我們編寫的函式
int mryang_probe(struct platform_device *pdv)
{
return 0;
}
int mryang_remove(struct platform_device *pdv)
{
return 0;
}
結構體裡的引數probe,remove函式已經定義完了,然後我們定義結構體時,把引數指向我們定義的probe和remove函式即可。
struct platform_driver mryang_driver = {
.probe = mryang_probe,
.remove = mryang_remove,
.driver = {
.name = "mryang_ctl", // 像這種變數最好定義一個巨集定義在開頭,別問我為啥
.owner = THIS_MODULE,
}
};
3. 收尾
現在我們驅動結構體也寫好了,那麼就可以註冊了,咋註冊,肯定是載入驅動的時候註冊,解除安裝驅動的時候解除安裝啊。
所以我們在mryang_init和mryang_exit裡分別添加註冊和解除安裝驅動的函式(要是不知道函式叫什麼,可以上翻檢視結構體的時候有說),引數自然就是我們定義的結構體mryang_driver。
// 寫在mryang_init裡
platform_driver_register(&mryang_driver);
// 寫在mryang_exit裡
platform_driver_unregister(&mryang_driver);
完整的程式碼
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("MrYang");
int mryang_probe(struct platform_device *pdv)
{
printk(KERN_EMERG "probe!\n");
return 0;
}
int mryang_remove(struct platform_device *pdv)
{
printk(KERN_EMERG "remove!\n");
return 0;
}
struct platform_driver mryang_driver = {
.probe = mryang_probe,
.remove = mryang_remove,
.driver = {
.name = "mryang_ctl", // 像這種變數最好定義一個巨集定義在開頭,別問我為啥
.owner = THIS_MODULE,
}
};
static int mryang_init(void)
{
printk(KERN_EMERG "HELLO MrYang\n");
platform_driver_register(&mryang_driver);
return 0;
}
static void mryang_exit(void)
{
printk(KERN_EMERG "Bye MrYang\n");
platform_driver_unregister(&mryang_driver);
}
module_init(mryang_init);
module_exit(mryang_exit);
Makefile檔案
#!/bin/bash
obj-m += probe_linux_module.o
KDIR := /root/iTop4412_Kernel_3.0
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o
其實看到Makefile基本上沒變,只是名字改成了probe_linux_module。以後就不再敘述Makefile了。
編譯驅動!
make
並非編譯linux核心哦,只是編譯驅動,不知道咋整詳見第一節…
載入、解除安裝驅動
[[email protected]]# insmod probe_linux_module.ko
[ 295.708430] HELLO MrYang
[ 295.709815] probe!
[[email protected]]# rmmod probe_linux_module
[ 297.924409] Bye MrYang
[ 297.925330] remove!
總結
其實也是融合了之前的所有內容
- 載入驅動呼叫了module_init(mryang_init);
其中的mryang_init是我們自定義的函式,裡面輸出了HELLO MrYang
- 緊接著還呼叫了註冊驅動的函式platform_driver_register(&mryang_driver);
mryang_driver就是我們定義的驅動的結構體,裡面包含了
probe和remove函式。
- 當我們註冊驅動的時候,發現裝置也註冊了,就呼叫probe函式
結構體內的probe指向了我們定義的mryang_probe(struct platform_device *pdv)函式
函式的內容就是輸出probe。
這就是完整的流程,你可能還會問,我們啥時候註冊裝置了?傻呀,看上一節註冊裝置的筆記,我們在編譯linux核心的時候已經勾選把註冊裝置也編譯進核心了。
至此,其實已經可以好好思考整個流程了。