文章转载至多个地方,网上拼凑的一篇文章,说的好听一些的话那就叫自己总结的文章,只 是多次引用啊,哈哈,哎,不管了,反正这个有利用学习进步就好,这是重要的,文章转载过来要经过一篇大脑才能成为自己的,以后千万要注意这点,不要把大好 的文章转载放在博客里面不管了,等到那一天遇到同样的问题了上网一搜搜到自己博客里面来了,嘿嘿。转入正题,linux设备驱动的总线,设备和驱动。

linux设备驱动的难点在于复杂的,庞大的结构。理清楚结构和一个结构与另外结构的关系,以及linux设备驱动的层次性和层次封装抽象性。对于linux设备驱动的结构有点像C++中的类,而层次与抽象有点像继承的关系。

一、总线、设备、驱动的主要三个结构关系

structbus_type  
---------------------------------
    struct bus_type中为devices和drivers准备了两个链表:
    struct klist klist_devices
    struct klist klist_drivers

struct device
---------------------------------
    struct device有两个成员
    struct bus_type      *bus     记录的是这个设备连在哪条总线上
    struct device_driver *driver 记录的是这个设备用的是哪个驱动

struct device_driver
---------------------------------
    struct device_driver同样有两个成员
    struct bus_type *bus          代表的是这个驱动属于哪条总线        
    struct klist    klist_devices 记录的是这个驱动支持的那些设备,没错,是devices(复数),因为一个驱动程序可以支持一个或多个设备,反过来一个设备则只会绑定给一个驱动程序.

二、总线,设备,驱动的关联

总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每 注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。一个现实的Linux设备和驱动通常都需要挂接在一种总线上。设备与驱动的关联通过总线的match()方法进行匹配,驱动挂载总线时与所有设备进行匹配,设备挂载总线时与所有的驱动进行匹配,所以驱动和设备的挂载无先后之分。匹配成功后会通过调用驱动的probo()方法来初始化设备。

三、总线,设备,驱动的注册

设备与驱动需要挂载在总线上,需要指明驱动与设备是属于哪条总线的,所以设备与驱动需要注册。而总线在linux系统中也是属于设备,所以总线也要注册,同时要先有总线而后才能注册设备和驱动,所以总线要先注册。

总 线在linux系统中有俩种,一是实际存在的总线 pci  usb 等等,还有一类是虚拟存在的总线 platform ,platform总线主要是用于集成在SoC系统的设备,使得每一个设备都属于一条总线,相应的设备称为platform_device,而驱动成为 platform_driver。linux驱动中platform总线用的非常多,以platform总线说明总线,设备,驱动的注册顺序,注意这里是以先调加设备为例。

1. platform_bus_type -- 总线 先被kenrel 注册。

2. 系统初始化过程中调用platform_add_devices 或者platform_device_register ,将平台设备(platform devices) 注册到平台总线中( platform_bus_type )
3. 平台驱动(platform driver) 与平台设备(platform device) 的关联是在platform_driver_register 或者driver_register 中实现,一般这个函数在驱动的初始化过程调用。

通过这三步,就将平台总线,设备,驱动关联起来。

1. platform bus 先被kenrel 注册。
------------------------------------------------------
do_basic_setup() --> - driver_init() --> - platform_bus_init() -->bus_register()

2. 系统初始化过程中调用platform_add_devices 或者platform_device_register ,将平台设备(platform devices) 注册到平台总线中( platform_bus_type )
------------------------------------------------------
系统启动阶段,总线的驱动链表还是空的,所以启动阶段的platform_add_devices() 只负责将设备添加到总线的设备链表上。

linux 2.6.26/drivers/base/platform.c
int platform_add_devices(struct platform_device **devs, int num)
{
     ...
     ret = platform_device_register (devs[i]);
     ...
}

int platform_device_register(struct platform_device *pdev)
{
     device_initialize(&pdev >dev);
     return platform_device_add (pdev);
}

int platform_device_add (struct platform_device *pdev)
{
     ...
     pdev >dev.bus = &platform_bus_type;
     ...
     ret = device_add (&pdev >dev);
     ...
}

device_add()   >   bus_attach_device()

void bus_attach_device(struct device *dev)
{
     struct bus_type *bus = dev >bus;
     int ret = 0;

if (bus) {
         if (bus >p >drivers_autoprobe)
             ret = device_attach (dev);
         WARN_ON(ret < 0);
         if (ret >= 0)
             klist_add_tail (&dev >knode_bus, &bus >p >klist_devices);
     }
}

device_attach() 的返回值:
1 设备和驱动匹配成功
0 设备已经注册,但是总线上没有与之相匹配的驱动( 系统启动阶段,由于总线上还没有驱动,所以设备在此匹配不到与之对应的驱动,只是将其添加到总线的设备链表)
-ENODEV 设备没有注册(registered) -- 设备在哪里注册?

如果设备和驱动匹配成功; 或者设备已经注册,但是总线上没有与之相匹配的驱动 ,bus_attach_device() 将调用klist_add_tail() 将设备添加到总线的设备链表尾部。

四、附录linux内核中的platform的几个结构源代码

view plain
  1. // 所在目录:kernel/include/linux/platform_device.h
  2. struct platform_device
  3. {
  4. const char  * name;/* 设备名 */
  5. u32      id;
  6. struct device dev;
  7. u32  num_resources;/* 设备所使用各类资源数量 */
  8. struct resource * resource;/* 资源 */
  9. };
  10. // 所在目录:include/linux/ioport.h
  11. struct resource
  12. {
  13. resource_size_t start;  /*  资源的开始值  */
  14. resource_size_t end;    /*  资源的结束值  */
  15. const char      *name;  /*  资源的名字  */
  16. unsigned long   flags;  /*  资源的类型值,如可以是:mem,io,irq,dma等等 */
  17. struct resource *parent, *sibling, *child;
  18. };
  19. // 所在目录:kernel/include/linux/ioport.h
  20. struct platform_driver
  21. {
  22. int (*probe)(struct platform_device *);
  23. int (*remove)(struct platform_device *);
  24. void (*shutdown)(struct platform_device *);
  25. int (*suspend)(struct platform_device *, pm_message_t state);
  26. int (*suspend_late)(struct platform_device *, pm_message_t state);
  27. int (*resume_early)(struct platform_device *);
  28. int (*resume)(struct platform_device *);
  29. struct pm_ext_ops *pm;
  30. struct device_driver driver;
  31. };
  32. // 所在目录:include/linux/device.h
  33. struct device_driver
  34. {
  35. char                    * name;
  36. struct bus_type         * bus;
  37. rwlock_t                lock;
  38. atomic_t                refcount;
  39. list_t                  bus_list;
  40. list_t                  devices;
  41. struct driver_dir_entry dir;
  42. int     (*probe)        (struct device * dev);
  43. int     (*remove)       (struct device * dev);
  44. int     (*suspend)      (struct device * dev, u32 state, u32 level);
  45. int     (*resume)       (struct device * dev, u32 level);
  46. void    (*release)      (struct device_driver * drv);
  47. };

文章内容多为转载,但是也经过我一番整理,发现其实整理一下自己也学到了很多。

linux设备驱动之总线、设备、驱动相关推荐

  1. linux用户空间flash驱动,全面掌握Linux驱动框架——字符设备驱动、I2C驱动、总线设备驱动、NAND FLASH驱动...

    原标题:全面掌握Linux驱动框架--字符设备驱动.I2C驱动.总线设备驱动.NAND FLASH驱动 字符设备驱动 哈~ 这几天都在发图,通过这种方式,我们希望能帮大家梳理学过的知识,全局的掌握Li ...

  2. linux下看pcie的设备id,linux lspci查看pci总线设备信息

    linux lspci查看pci总线设备信息 linux中lspci是一个用来显示系统中所有PCI总线设备或连接到该总线上的所有设备的工具,比如查看网卡.存储等信息. 参数 -v 使得 lspci 以 ...

  3. Linux SPI总线设备驱动模型详解

    随着技术不断进步,系统的拓扑结构越来越复杂,对热插拔.跨平台移植性的要求越来越高,早期的内核难以满足这些要求,从linux2.6内核开始,引入了总线设备驱动模型.其实在linux2.4总线的概念就已经 ...

  4. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之总线设备驱动模型

    文章目录 前言 1.驱动编写的三种方法 1.1.传统写法 1.2.总线驱动模型 1.3.设备树驱动模型 2.Linux实现分离:Bus/Dev/Drv模型 2.1.Bus/Dev/Drv模型 2.2. ...

  5. linux设备模型——总线,驱动,设备间的关系

    设备模型之kobject,kset及其关系 关于linux设备模型kobject,kset,ktype 设备驱动基础0:设备模型之kobject,kset及其关系 设备模型之总线,驱动,设备 Linu ...

  6. linux一个spi总线挂多个设备,Linux SPI总线设备驱动模型详解

    随着技术不断进步,系统的拓扑结构越来越复杂,对热插拔.跨平台移植性的要求越来越高,早期的内核难以满足这些要求,从linux2.6内核开始,引入了总线设备驱动模型.其实在linux2.4总线的概念就已经 ...

  7. Linux 设备驱动开发 —— platform 设备驱动

    一.platform总线.设备与驱动         在Linux 2.6 的设备驱动模型中,关心总线.设备和驱动3个实体,总线将设备和驱动绑定.在系统每注册一个设备的时候,会寻找与之匹配的驱动:相反 ...

  8. 设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动

    以下内容转载于微信公众号:嵌入式企鹅圈.如有侵权,请告知删除. 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sysfs等相关概念和技术. 对于初学者来说会非常 ...

  9. Linux驱动(9)--注册设备

    注册设备 1. 总线设备驱动注册流程 2. 以内核的方式注册设备 3. 以module的方式注册设备 4. 注意 1. 总线设备驱动注册流程 Linux下的总线设备驱动注册流程如下图所示: ① Lin ...

  10. Linux设备管理(三)_总线设备的挂接

    扒完了字符设备,我们来看看平台总线设备,平台总线是Linux中的一种虚拟总线,我们知道,总线+设备+驱动是Linux驱动模型的三大组件,设计这样的模型就是将驱动代码和设备信息相分离,对于稍微复杂一点的 ...

最新文章

  1. Java项目:朴素风个人博客系统(前后端分离+java+vue+Springboot+ssm+mysql+maven+redis)
  2. 任正非签发最新电邮:过去我们是为了赚点小钱,现在是要战胜美国
  3. LTE-V2X车联网无线通信技术发展
  4. tomcat启动报错
  5. 搞科研、学术的朋友注意了,停下手头的活,再忙也要看一下这个!
  6. springboot加入com.fasterxml.jackson.core-jackson-databind依赖后报错Error creating bean with name ‘requestM
  7. 进程间通信之分别用共享内存和信号量实现卖票
  8. WPF在不同.Net版本间的兼容性问题
  9. cocos2dx对于强大的RichText控制
  10. linux之systemctl命令
  11. 网页设计基础知识总结
  12. NCBI引物设计-查找目的基因前后序列方法、序列比对
  13. TIA Portal联合Process Simulate搞定SICAR虚拟调试实例步骤
  14. Nodejs写的搬家工具知识分享
  15. 【MATLAB】修改黑色炫酷主题darcula.prf
  16. matlab fig图片读取,从Matlab .fig文件中读取数据,并重新绘图
  17. A4宣传单正常规格是210*285mm,每边各留3mm出血位。
  18. RocketMQ Message相关命令【实战笔记】
  19. 【数据库 · MySQL】听韩顺平老师课草稿
  20. 你可能会读错的字大集合

热门文章

  1. 每日一皮:以为是王者,没想到是个青铜...
  2. 如何停止一个正在运行的线程?
  3. 每日一问一周汇总:第1期
  4. 检测到磁盘可能为uefi引导_重装系统win10提示磁盘布局不受UEFI固件支持怎么办...
  5. java filesystem 追加_java 如何往已经存在的excel表格里面追加数据的方法
  6. 【并发编程】线程等待、通知(wait/notify)
  7. cmakelist 定义变量
  8. android OkHttp form 上传图片和参数
  9. skimage 学习笔记
  10. 'str' object is not callable