現在的位置: 首頁 > 綜合 > 正文

linux設備驅動歸納總結(八):3.設備模型的分層與面向對象

2018年03月16日 ⁄ 綜合 ⁄ 共 7110字 ⁄ 字型大小 評論關閉

原文地址:linux設備驅動歸納總結(八)3設備模型的分層與面向對象
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=3631835&fromuid=28801784

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

前面的內容介紹了匯流排、設備和驅動函數的關係和操作。從這節開始,介紹設備管理中的分層思想和面向對象思想(名字是我自己瞎編的,《LDD》上指的是結構體內嵌)。可以理解是平台類設備(platform)的一個過度。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

一、設備管理的分層

回想一下之前的設備和驅動函數註冊時,它們是自己指定所屬的匯流排。但是,內核開發人員覺得,這樣的方法不好,應該由匯流排來提供設備和驅動的註冊函數。當設備和驅動需要註冊到指定匯流排時,那就必須使用該匯流排為設備和驅動提供的註冊函數。

所以,將上一節的bus.c修改如下:

/*8th_devModule_3/1st/bus.c*/

21 /*匯流排提供的設備註冊函數*/

22 int usb_device_register(struct device *dev)

23 {

24     dev->bus = &usb_bus; //設備device的匯流排為usb_bus

25     return device_register(dev); //註冊此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 /*匯流排提供的驅動註冊函數*/

34 int usb_driver_register(struct device_driver *drv)

35 {

36     drv->bus = &usb_bus; //設置driver的匯流排為usb_bus

37     return driver_register(drv); //註冊此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);

再寫一個bus.h,讓設備和驅動函數包含該頭文件後能夠使用匯流排提供的驅動函數。

/*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 */

上面的程序可以看到,其實也沒幹什麼事情,只是由匯流排來封裝並且向設備和驅動函數提供註冊函數,便於管理。而不像以前,設備和驅動只要知道匯流排的名字,就能註冊到指定的匯流排中。

再修改一下設備和驅動函數的代碼:

/*8th_devModule_3/1st/device.c*/

11 /*結構體中不需要指定匯流排的成員,交由usb_device_register來完成*/

12 struct device usb_device = {

13     .bus_id = "usb_mouse",

14     .release = usb_dev_release, //必須要都有release函數,不然卸載時會出錯

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 /*結構體中不需要指定匯流排的成員,交由usb_device_register來完成*/

25 struct device_driver usb_driver = {

26    .name = "usb_mouse", ///sys/中的驅動目錄名字

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    /*驅動註冊,註冊成功後在/sys/bus/usb/driver目錄下創建目錄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 }

修改完畢,驗證一下,效果和之前的一樣,我也不詳細解釋:

[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!

二、面向對象思想——結構內嵌

device結構體分別包含了設備模型的基本信息。然後,大多數的子系統還會記錄該結構體以外但與設備相關的信息。因此,單純用一個device結構來表示設備是很少見的,而是把device結構體內嵌到其他的結構體中。當然,device_driver也是一樣。

接下來,我封裝一下設備和驅動函數的結構體:

/*8th_devModule_3/2nd/bus.h*/

4 struct
usb_device
{ //
usb_device中包含device結構體

5    unsigned long phys, virt; //存放設備和物理地址和對應的虛擬地址

6    int irq; //存放設備的中斷號

7    int VendorID, DeviceID; //存放設備的生產廠商編號和設備編號

8

9    struct device dev;

10 };

11

12 struct
usb_driver
{ //
usb_driver中包含device_driver結構體

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 */

在上面,我將設備結構體device內嵌到usb_device結構體中,該結構體中還有成員生產廠商編號和設備編號,在match函數會用來配對,成員irqphysvirt在接下來的章節會用到。

同樣的,驅動函數結構體device_driver被內嵌到usb_driver結構體中,該結構體中還有成員生產廠商編號和設備編號,在match函數中會用來匹配。

因為我定義了新的結構體,三個函數都的傳參都有了稍稍的改變。

首先是bus.c

/*8th_devModule_3/2nd/bus.c*/

7 int usb_bus_match(struct device *dev, struct device_driver *drv)

8 { /*使用container_of找出匯流排自己定義的結構體*/

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    /*配對函數判斷驅動和設備的生產廠商編號和設備編號是否一致*/

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中的配對函數被我修改了兩部分:

1、通過container_of來獲得usb_deviceusb_driver結構體。

2、修改了配對了方法,通過判斷兩者生產廠商編號與設備號是否都一致。

因為定義了新的結構體,所以我將註冊函數的參數也修改了。

/*8th_devModule_3/2nd/bus.c*/

26 /*匯流排提供的設備註冊函數*/

27 int usb_device_register(struct
usb_device *usb_dev
)

28 {

29    usb_dev->dev.bus = &usb_bus; //設備device的匯流排為usb_bus

30    return device_register(&usb_dev->dev); //註冊此device

31 }

32 void usb_device_unregister(structusb_device *usb_dev)

33 {

34    device_unregister(&usb_dev->dev);

35 }

36 EXPORT_SYMBOL(usb_device_register);

37 EXPORT_SYMBOL(usb_device_unregister);

38 /*匯流排提供的驅動註冊函數*/

39 int usb_driver_register(struct
usb_driver *usb_drv
)

40 {

41    usb_drv->drv.bus = &usb_bus; //設置driver的匯流排為usb_bus

42    return driver_register(&usb_drv->drv); //註冊此driver

43 }

44 void usb_driver_unregister(structusb_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/中的驅動目錄名字

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    /*驅動註冊,註冊成功後在/sys/bus/usb/driver目錄下創建目錄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 }

修改完畢,看看效果,其實就是和之前一模一樣。

[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

三、總結

這節內容並不多,其實就是修改修改一下原來的代碼,等到我介紹平台類設備的時候你就會發現,其實平台類就是這樣一步步封裝起來的(當然比我的複雜)。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

抱歉!評論已關閉.