查看: 1921|回复: 0

[基础] linux总线设备驱动模型

[复制链接]
  • TA的每日心情
    开心
    2015-7-14 09:10
  • 签到天数: 9 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2017-8-10 13:23:03 | 显示全部楼层 |阅读模式
    分享到:
    目录:
    1.总线设备模型概述
    2.总线
    3.驱动
    4.设备
    1.总线设备模型概述
    随着技术的不断进步,系统的拓扑结构也越来越复杂,对热插拔,跨平台移植性的要求也越来越高,2.4内核已经难以满足这些需求。为适应这种形势的需要,从Linux2.6内核开始提供了全新的设备模型。总线设备驱动对热插拔要求越来越高。
    Linux系统中,有很多总线,例如USB总线挂载很多USB设备驱动程序(鼠标,USB网卡),往USB总线上插入一个USB网卡设备,USB总线感知到一个新的设备上到总线上并且是USB的,总线会把总线上的每一个驱动与USB网卡设备匹配,匹配成功后usb总线将控制权交给USB网卡驱动程序,USB驱动程序开始处理USB网卡设备。设备从总线拔掉,USB总线感知USB网卡设备拔掉,USB总线将找到相应的USB网卡驱动程序将处理设备拔掉这个事件。
    网卡从USB换成miniPCI,需要修改的特别少,增强了驱动程序的可移植性。
    当往总线上插入一个设备,总线有义务将设备与驱动进行匹配,有match函数完成是否可以匹配。匹配成功调用probe函数
    以下将从创建总线、创建驱动,创建设备3个方面进行总线设备挂载到总线上的流程进行介绍。
    2.总线
    2.1描述结构
    linux 内核中, 总线由bus_type 结构表示,定义在
    1. #include<linux/device.h>
    2. struct bus_type {
    3. const char *name; /*总线名称*/
    4. int (*match) (struct device *dev, struct device_driver *drv); /*驱动与设备的匹配函数*/
    5. }
    6. int (*match)(struct device * dev, struct device_driver * drv)
    复制代码
    当一个新设备或者新驱动被添加到这个总线时,该函数被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零。
    2.2总线注册
    总线的注册使用如下函数
    bus_register(struct bus_type *bus)
    若成功,新的总线将被添加进系统,并可在
    /sys/bus 下看到相应的目录。
    2.3总线注销
    总线的注销使用:
    void bus_unregister(struct bus_type *bus)
    1. bus.c
    2. #include<linux/init.h>
    3. #include<linux/module.h>
    4. #include<linux/kernel.h>
    5. #include<linux/device.h>
    6. MODULE_LICENSE("GPL");
    7. int my_match(struct device *dev, struct device_driver *drv)
    8. {
    9.      return !strncmp(dev->kobj.name,drv->name,strlen(drv->name));
    10. }
    11. struct bus_type my_bus_type = {
    12.     .name = "my_bus",
    13.     .match = my_match,
    14. };
    15. EXPORT_SYMBOL(my_bus_type);//将变量输出,供外部使用
    16. int my_bus_init()
    17. {
    18.     int ret;
    19.     ret=bus_register(&my_bus_type);
    20.     return ret;
    21. }
    22. void my_bus_exit()
    23. {
    24.     bus_unregister(&my_bus_type);
    25. }
    26. module_init(my_bus_init);
    27. module_exit(my_bus_exit);
    复制代码
    insmod bus.ko加载驱动、向系统注册总线
    lsmod
    查看总线课通过cd /sys/bus,ls即可查看linux支持的总线
    3.驱动
    3.1描述结构
    在Linux内核中, 驱动由device_driver结构表示。
    struct device_driver {
    {
    const char name; /驱动名称*/
    struct bus_type bus; /驱动程序所在的总线*/
    int (*probe) (struct device *dev);
    ………
    }
    3.2驱动注册
    驱动的注册使用如下函数
    int driver_register(struct device_driver *drv)
    3.3驱动注销
    驱动的注销使用:
    void driver_unregister(struct device_driver *drv)
    1. driver.c
    2. #include<linux/module.h>
    3. #include<linux/init.h>
    4. #include<linux/device.h>
    5. #include<linux/kernel.h>

    6. extern struct bus_type my_bus_type;//变量来自于外部
    7. MODULE_LICENSE("GPL");
    8. int my_probe(struct device *dev)
    9. {
    10.     printk("the bus's driver find the device it can handle\n ");
    11.     //实际的硬件设备初始化


    12. }

    13. struct device_driver my_driver = {
    14.     .name = "my_dev",//驱动名称
    15.     .bus = &my_bus_type,//所挂载的总线
    16.     .probe = my_probe,//匹配调用函数

    17. };

    18. int my_driver_init()
    19. {
    20.     int ret;
    21.     ret =driver_register(&my_driver);
    22.     return ret;

    23. }
    24. void my_driver_exit()
    25. {
    26.     driver_unregister(&my_driver);
    27. }

    28. module_init(my_driver_init);
    29. module_exit(my_driver_exit);
    复制代码
    insmod driver.ko
    cd /sys/bus/
    ls即可看到my-bus总线
    cd drivers/
    ls
    即可查看重新注册的驱动my_dev
    4.设备
    4.1设备描述结构
    在Linux内核中, 设备由struct device结构表示。
    struct device {
    {
    const char init_name; /设备的名字*/
    struct bus_type bus; /设备所在的总线*/
    ………
    }
    4.2设备注册
    设备的注册使用如下函数
    int device_register(struct device *dev)
    4.3设备注销
    设备的注销使用:
    void device_unregister(struct device *dev)
    1. device.v
    2. #include<linux/init.h>
    3. #include<linux/module.h>
    4. #include<linux/kernel.h>
    5. #include<linux/device.h>


    6. MODULE_LICENSE("GPL");

    7. extern struct bus_type my_bus_type;

    8. struct device my_device = {
    9.     .init_name = "my_dev",
    10.     .bus = &my_bus_type,
    11. };

    12. int my_device_init()
    13. {
    14.     int ret;
    15.     ret = device_register(&my_device);
    16.     return ret;
    17. }
    18. void my_device_exit()
    19. {   
    20.     dvice_unregister(&my_device);
    21. }
    22. module_init(my_device_init);
    23. module_exit(my_device_exit);
    复制代码
    insmod bus.ko
    insmod driver.c
    insmod device.c
    #
    the bus’s driver find the device it can handle
    总结:
    1.总线上已经挂载设备驱动程序,当向总线添加设备,总线匹配成功,调用驱动1的probe函数
    2.总线上已经挂载多个设备,后加载一个驱动程序,将驱动与每个设备匹配,匹配成功,调用驱动probe函数



    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条



    手机版|小黑屋|与非网

    GMT+8, 2025-1-12 13:38 , Processed in 0.114748 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.