1. 程式人生 > >【迅為iTop4412學習筆記】6. 驅動註冊

【迅為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!

總結

其實也是融合了之前的所有內容

  1. 載入驅動呼叫了module_init(mryang_init);

其中的mryang_init是我們自定義的函式,裡面輸出了HELLO MrYang

  1. 緊接著還呼叫了註冊驅動的函式platform_driver_register(&mryang_driver);

mryang_driver就是我們定義的驅動的結構體,裡面包含了
probe和remove函式。

  1. 當我們註冊驅動的時候,發現裝置也註冊了,就呼叫probe函式

結構體內的probe指向了我們定義的mryang_probe(struct platform_device *pdv)函式
函式的內容就是輸出probe。

這就是完整的流程,你可能還會問,我們啥時候註冊裝置了?傻呀,看上一節註冊裝置的筆記,我們在編譯linux核心的時候已經勾選把註冊裝置也編譯進核心了。

至此,其實已經可以好好思考整個流程了。