zoukankan      html  css  js  c++  java
  • 【Linux开发】linux设备驱动归纳总结(八):3.设备管理的分层与面向对象思想

    linux设备驱动归纳总结(八):3.设备管理的分层与面向对象思想


    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! ");

    24     return ret;

    25     }

    26

    27     printk("usb device init ");

    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! ");

    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! ");

    38     return ret;

    39     }

    40     printk("usb driver init ");

    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! ");

    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

    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结构体

        unsigned long phys, virt; //存放设备和物理地址和对应的虚拟地址

        int irq; //存放设备的中断号

        int VendorID, DeviceID; //存放设备的生产厂商编号和设备编号

    8

        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找出总线自己定义的结构体*/

          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 ");

    15         return 1;

    16     }else{

    17         printk("match failed ");

    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(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 /*总线提供的驱动注册函数*/

    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(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! ");

    28         return ret;

    29     }

    30

    31     printk("usb device init ");

    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! ");

    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! ");

    42         return ret;

    43     }

    44     printk("usb driver init ");

    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! ");

    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

    release

    usb device bye!

    [root: 2nd]# rmmod driver

    usb driver bye!

    [root: 2nd]# rmmod bus

    usb bus bye!


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    三、总结


    这节内容并不多,其实就是修改修改一下原来的代码,等到我介绍平台类设备的时候你就会发现,其实平台类就是这样一步步封装起来的(当然比我的复杂)。


    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    源代码: 8th_devModule_3.rar   

  • 相关阅读:
    JNI实例(含代码)
    sizeof()小结
    【转】C++ 关键字——friend
    curl资料小结
    【Curl (libcurl) 开发 之一】Cocos2dx之libcurl(curl_easy)的编程教程(帮助手册)!
    JSP中统一错误信息输出
    在号码池取连续号码的算法
    常用的文件操作方法
    走出基金净值的误区
    ResultSet概论
  • 原文地址:https://www.cnblogs.com/huty/p/8518557.html
Copyright © 2011-2022 走看看