linux設(shè)備驅(qū)動(dòng)歸納總結(jié)(八):3.設(shè)備管理的分層與面向?qū)ο笏枷?/FONT>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
前面的內(nèi)容介紹了總線、設(shè)備和驅(qū)動(dòng)函數(shù)的關(guān)系和操作。從這節(jié)開始,介紹設(shè)備管理中的分層思想和面向?qū)ο笏枷耄质俏易约合咕幍,《LDD》上指的是結(jié)構(gòu)體內(nèi)嵌)?梢岳斫馐瞧脚_(tái)類設(shè)備(platform)的一個(gè)過度。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
一、設(shè)備管理的分層
回想一下之前的設(shè)備和驅(qū)動(dòng)函數(shù)注冊(cè)時(shí),它們是自己指定所屬的總線。但是,內(nèi)核開發(fā)人員覺得,這樣的方法不好,應(yīng)該由總線來提供設(shè)備和驅(qū)動(dòng)的注冊(cè)函數(shù)。當(dāng)設(shè)備和驅(qū)動(dòng)需要注冊(cè)到指定總線時(shí),那就必須使用該總線為設(shè)備和驅(qū)動(dòng)提供的注冊(cè)函數(shù)。
所以,將上一節(jié)的bus.c修改如下:
/*8th_devModule_3/1st/bus.c*/
21 /*總線提供的設(shè)備注冊(cè)函數(shù)*/
22 int usb_device_register(struct device *dev)
23 {
24 dev->bus = &usb_bus; //設(shè)備device的總線為usb_bus
25 return device_register(dev); //注冊(cè)此device
26 }
27 void usb_device_unregister(struct device *dev)
28 {
29 device_unregister(dev);
30 }
31 EXPORT_SYMBOL(usb_device_register);
32 EXPORT_SYMBOL(usb_device_unregister);
33 /*總線提供的驅(qū)動(dòng)注冊(cè)函數(shù)*/
34 int usb_driver_register(struct device_driver *drv)
35 {
36 drv->bus = &usb_bus; //設(shè)置driver的總線為usb_bus
37 return driver_register(drv); //注冊(cè)此driver
38 }
39 void usb_driver_unregister(struct device_driver *drv)
40 {
41 driver_unregister(drv);
42 }
43 EXPORT_SYMBOL(usb_driver_register);
44 EXPORT_SYMBOL(usb_driver_unregister);
再寫一個(gè)bus.h,讓設(shè)備和驅(qū)動(dòng)函數(shù)包含該頭文件后能夠使用總線提供的驅(qū)動(dòng)函數(shù)。
/*8th_devModule_3/1st/bus.h*/
1 #ifndef _BUS_H
2 #define _BUS_H
3
4 int usb_device_register(struct device *dev);
5 void usb_device_unregister(struct device *dev);
6
7 int usb_driver_register(struct device_driver *drv);
8 void usb_driver_unregister(struct device_driver *drv);
9 #endif /* _BUS_H */
上面的程序可以看到,其實(shí)也沒干什么事情,只是由總線來封裝并且向設(shè)備和驅(qū)動(dòng)函數(shù)提供注冊(cè)函數(shù),便于管理。而不像以前,設(shè)備和驅(qū)動(dòng)只要知道總線的名字,就能注冊(cè)到指定的總線中。
再修改一下設(shè)備和驅(qū)動(dòng)函數(shù)的代碼:
/*8th_devModule_3/1st/device.c*/
11 /*結(jié)構(gòu)體中不需要指定總線的成員,交由usb_device_register來完成*/
12 struct device usb_device = {
13 .bus_id = "usb_mouse",
14 .release = usb_dev_release, //必須要都有release函數(shù),不然卸載時(shí)會(huì)出錯(cuò)
15 };
16
17 static int __init usb_device_init(void)
18 {
19 int ret;
20
21 ret = usb_device_register(&usb_device);
22 if(ret){
23 printk("device register failed!\n");
24 return ret;
25 }
26
27 printk("usb device init\n");
28 return 0;
29 }
30
31 static void __exit usb_device_exit(void)
32 {
33 usb_device_unregister(&usb_device);
34 printk("usb device bye!\n");
35 }
/*8th_devModule_3/1st/driver.c*/
24 /*結(jié)構(gòu)體中不需要指定總線的成員,交由usb_device_register來完成*/
25 struct device_driver usb_driver = {
26 .name = "usb_mouse", //在/sys/中的驅(qū)動(dòng)目錄名字
27 .probe = usb_driver_probe,
28 .remove = usb_driver_remove,
29 };
30
31 static int __init usb_driver_init(void)
32 {
33 int ret;
34 /*驅(qū)動(dòng)注冊(cè),注冊(cè)成功后在/sys/bus/usb/driver目錄下創(chuàng)建目錄usb_mouse*/
35 ret = usb_driver_register(&usb_driver);
36 if(ret){
37 printk("driver register failed!\n");
38 return ret;
39 }
40 printk("usb driver init\n");
41 return 0;
42 }
43
44 static void __exit usb_driver_exit(void)
45 {
46 usb_driver_unregister(&usb_driver);
47 printk("usb driver bye!\n");
48 }
修改完畢,驗(yàn)證一下,效果和之前的一樣,我也不詳細(xì)解釋:
[root: 1st]# insmod bus.ko
usb bus init
[root: 1st]# insmod device.ko
usb device init
[root: 1st]# insmod driver.ko
match success
match success
init usb mouse
usb driver init
[root: 1st]# rmmod device
remove mouse driver
<kernel> release
usb device bye!
[root: 1st]# rmmod driver
usb driver bye!
[root: 1st]# rmmod bus
usb bus bye!
二、面向?qū)ο笏枷搿Y(jié)構(gòu)內(nèi)嵌
device結(jié)構(gòu)體分別包含了設(shè)備模型的基本信息。然后,大多數(shù)的子系統(tǒng)還會(huì)記錄該結(jié)構(gòu)體以外但與設(shè)備相關(guān)的信息。因此,單純用一個(gè)device結(jié)構(gòu)來表示設(shè)備是很少見的,而是把device結(jié)構(gòu)體內(nèi)嵌到其他的結(jié)構(gòu)體中。當(dāng)然,device_driver也是一樣。
接下來,我封裝一下設(shè)備和驅(qū)動(dòng)函數(shù)的結(jié)構(gòu)體:
/*8th_devModule_3/2nd/bus.h*/
4 struct usb_device{ //在usb_device中包含device結(jié)構(gòu)體
5 unsigned long phys, virt; //存放設(shè)備和物理地址和對(duì)應(yīng)的虛擬地址
6 int irq; //存放設(shè)備的中斷號(hào)
7 int VendorID, DeviceID; //存放設(shè)備的生產(chǎn)廠商編號(hào)和設(shè)備編號(hào)
8
9 struct device dev;
10 };
11
12 struct usb_driver{ //在usb_driver中包含device_driver結(jié)構(gòu)體
13 int VendorID, DeviceID;
14
15 struct device_driver drv;
16 };
17
18 int usb_device_register(struct usb_device *usb_dev);
19 void usb_device_unregister(struct usb_device *usb_dev);
20
21 int usb_driver_register(struct usb_driver *usb_drv);
22 void usb_driver_unregister(struct usb_driver *usb_drv);
23 #endif /* _BUS_H */
在上面,我將設(shè)備結(jié)構(gòu)體device內(nèi)嵌到usb_device結(jié)構(gòu)體中,該結(jié)構(gòu)體中還有成員生產(chǎn)廠商編號(hào)和設(shè)備編號(hào),在match函數(shù)會(huì)用來配對(duì),成員irq、phys和virt在接下來的章節(jié)會(huì)用到。
同樣的,驅(qū)動(dòng)函數(shù)結(jié)構(gòu)體device_driver被內(nèi)嵌到usb_driver結(jié)構(gòu)體中,該結(jié)構(gòu)體中還有成員生產(chǎn)廠商編號(hào)和設(shè)備編號(hào),在match函數(shù)中會(huì)用來匹配。
因?yàn)槲叶x了新的結(jié)構(gòu)體,三個(gè)函數(shù)都的傳參都有了稍稍的改變。
首先是bus.c:
/*8th_devModule_3/2nd/bus.c*/
7 int usb_bus_match(struct device *dev, struct device_driver *drv)
8 { /*使用container_of找出總線自己定義的結(jié)構(gòu)體*/
9 struct usb_device *usb_dev = container_of(dev, struct usb_device, dev);
10 struct usb_driver *usb_drv = container_of(drv, struct usb_driver, drv);
11 /*配對(duì)函數(shù)判斷驅(qū)動(dòng)和設(shè)備的生產(chǎn)廠商編號(hào)和設(shè)備編號(hào)是否一致*/
12 if((usb_dev->VendorID == usb_drv->VendorID) &&
13 (usb_dev->DeviceID == usb_drv->DeviceID)){
14 printk("match success\n");
15 return 1;
16 }else{
17 printk("match failed\n");
18 return 0;
19 }
20 }
bus.c中的配對(duì)函數(shù)被我修改了兩部分:
1、通過container_of來獲得usb_device和usb_driver結(jié)構(gòu)體。
2、修改了配對(duì)了方法,通過判斷兩者生產(chǎn)廠商編號(hào)與設(shè)備號(hào)是否都一致。
因?yàn)槎x了新的結(jié)構(gòu)體,所以我將注冊(cè)函數(shù)的參數(shù)也修改了。
/*8th_devModule_3/2nd/bus.c*/
26 /*總線提供的設(shè)備注冊(cè)函數(shù)*/
27 int usb_device_register(struct usb_device *usb_dev)
28 {
29 usb_dev->dev.bus = &usb_bus; //設(shè)備device的總線為usb_bus
30 return device_register(&usb_dev->dev); //注冊(cè)此device
31 }
32 void usb_device_unregister(struct usb_device *usb_dev)
33 {
34 device_unregister(&usb_dev->dev);
35 }
36 EXPORT_SYMBOL(usb_device_register);
37 EXPORT_SYMBOL(usb_device_unregister);
38 /*總線提供的驅(qū)動(dòng)注冊(cè)函數(shù)*/
39 int usb_driver_register(struct usb_driver *usb_drv)
40 {
41 usb_drv->drv.bus = &usb_bus; //設(shè)置driver的總線為usb_bus
42 return driver_register(&usb_drv->drv); //注冊(cè)此driver
43 }
44 void usb_driver_unregister(struct usb_driver *usb_drv)
45 {
46 driver_unregister(&usb_drv->drv);
47 }
48 EXPORT_SYMBOL(usb_driver_register);
49 EXPORT_SYMBOL(usb_driver_unregister);
接著是device.c:
/*8th_evModule_3/2nd/device.c*/
12 struct usb_device mouse_dev = {
13 .VendorID = 0x1122,
14 .DeviceID = 0x3344,
15 .dev = {
16 .bus_id = "usb_mouse",
17 .release = usb_dev_release,
18 },
19 };
20
21 static int __init usb_device_init(void)
22 {
23 int ret;
24
25 ret = usb_device_register(&mouse_dev);
26 if(ret){
27 printk("device register failed!\n");
28 return ret;
29 }
30
31 printk("usb device init\n");
32 return 0;
33 }
34
35 static void __exit usb_device_exit(void)
36 {
37 usb_device_unregister(&mouse_dev);
38 printk("usb device bye!\n");
39 }
最后再看看driver.c:
/*8th_devModule_3/2nd/driver.c*/
25 struct usb_driver mouse_drv = {
26 .VendorID = 0x1122,
27 .DeviceID = 0x3344,
28 .drv = {
29 .name = "usb_mouse", //在/sys/中的驅(qū)動(dòng)目錄名字
30 .probe = usb_driver_probe,
31 .remove = usb_driver_remove,
32 },
33 };
34
35 static int __init usb_driver_init(void)
36 {
37 int ret;
38 /*驅(qū)動(dòng)注冊(cè),注冊(cè)成功后在/sys/bus/usb/driver目錄下創(chuàng)建目錄usb_mouse*/
39 ret = usb_driver_register(&mouse_drv);
40 if(ret){
41 printk("driver register failed!\n");
42 return ret;
43 }
44 printk("usb driver init\n");
45 return 0;
46 }
47
48 static void __exit usb_driver_exit(void)
49 {
50 usb_driver_unregister(&mouse_drv);
51 printk("usb driver bye!\n");
52 }
修改完畢,看看效果,其實(shí)就是和之前一模一樣。
[root: /]# cd review_driver/8th_devModule/8th_devModule_3/2nd/
[root: 2nd]# insmod bus.ko
usb bus init
[root: 2nd]# insmod device.ko
usb device init
[root: 2nd]# insmod driver.ko
match success
match success
init usb mouse
usb driver init
[root: 2nd]# rmmod device
remove mouse driver
<kernel> release
usb device bye!
[root: 2nd]# rmmod driver
usb driver bye!
[root: 2nd]# rmmod bus
usb bus bye!
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
三、總結(jié)
這節(jié)內(nèi)容并不多,其實(shí)就是修改修改一下原來的代碼,等到我介紹平臺(tái)類設(shè)備的時(shí)候你就會(huì)發(fā)現(xiàn),其實(shí)平臺(tái)類就是這樣一步步封裝起來的(當(dāng)然比我的復(fù)雜)。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
源代碼: 8th_devModule_3.rar
|