一 设备驱动模型三个重要组件

总线 设备 驱动

1.1 总线

1.总线是物理总线和的抽象,虚拟总线的描述
2.设备驱动模型中驱动程序依附在总线上

1.2 三者之间的联系

在上一节说到sys下每一个目录都由kobject映射
sys目录下有一个bus目录,所有总线都保存在bus下,一般一个总线目录下都会有一些设备目录和驱动目录(kobject)以及一些总线属性文件(ktype)

设备目录中包含挂接在该总线上的设备
驱动目录包含挂接在该总线上的驱动程序,都是使用链表去组织
设备和驱动程序之间通过指针相互联系

1.3 描述总线的数据结构bus_type

在设备驱动模型中 总线使用bus_type描述。只要有一条新总线,就需要由bus_type结构实例化出一个对象出来:

源码地址:/include/linux/device/bus.h

name对应总线的名称
bus_attrs, dev_attrs drv_attrs对应则上一节中的attribute类型的变量,与他类似,但是包含了更定制化的信息。
probe ---- 探测设备函数
match ----匹配函数,检验参数 2 中的驱动是否支持参数 1 中的设备
uevent,remove,suspend,resume都是电源管理相关的函数

在linux系统中电源管理一直都是非常重要的部分 省电模式模式下系统的设备以一定的先后顺序挂起
全速工作模式下系统中的设备以一定的先后顺序恢复运行 一条总线上所有设备都挂起时总线才会挂起 一条总线上有任意一个设备要恢复之前总线必须恢复
由于这个管理功能对于大多模块都是必须的,所以将他抽象到更深的层次上

dev_pm_ops *pm是关于电源管理的操作符
bus_type_private表示总线私有数据

struct bus_type {const char      *name;const char        *dev_name;struct device     *dev_root;const struct attribute_group **bus_groups;const struct attribute_group **dev_groups;const struct attribute_group **drv_groups;int (*match)(struct device *dev, struct device_driver *drv);int (*uevent)(struct device *dev, struct kobj_uevent_env *env);int (*probe)(struct device *dev);void (*sync_state)(struct device *dev);void (*remove)(struct device *dev);void (*shutdown)(struct device *dev);int (*online)(struct device *dev);int (*offline)(struct device *dev);int (*suspend)(struct device *dev, pm_message_t state);int (*resume)(struct device *dev);int (*num_vf)(struct device *dev);int (*dma_configure)(struct device *dev);const struct dev_pm_ops *pm;const struct iommu_ops *iommu_ops;struct subsys_private *p;struct lock_class_key lock_key;bool need_parent_lock;
};

使用bus_type实例化对象时,就是对物理总线进行抽象,也是对虚拟总线进行描述的过程
(大名鼎鼎的platform平台设备总线就是虚拟总线,往后会介绍)
bus_type的实例化十分简单,因为有很多成员使用不到,ac97声卡的总线定义:

struct bus_type ac97_bus_type = {.name = "ac97",
.match = ac97_bus_match,
#ifdef CONFIG_PM
.suspend = ac97_bus_suspend,
.resume = ac97_bus_resume,
#endif /* CONFIG_PM */
};

使用bus_type_private实例化对象时,最主要的是填写前三个kset变量的信息:
subsys代表该 bus 子系统,里面的 kobj 是该 bus 的主kobj,也就是最顶层
drivers_kset指向挂接到该总线上的所有驱动集合
devices_kset;挂接到该总线上的所有设备集合

经过对上面两个重要结构体的填写,已经基本具备了总线驱动设备模型的框架
此时只需要对总线进行注册:bus_register()
bus_register()函数对 bus_type 进行注册,当从系统中删除一条总线时,应该使用
bus_unregister()函数。

int bus_register(struct bus_type *bus)
{int retval; /*返回值*/
struct bus_type_private *priv; /*总线私有数据*/
priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
/*申请一个总线私有数据结构*/
if (!priv) /*内存不足,返回*/
return -ENOMEM;
priv->bus = bus; /*总线私有数据结构回指的总线*/
bus->p = priv; /*总线的私有数据*/
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);/*初始化通知链表*/
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
/*设置总线的名字,例如 PCI*/
if (retval) /*失败则返回*/
goto out;
priv->subsys.kobj.kset = bus_kset;
/*指向其父 kset,bus_kset 在 buses_init()例程中添加*/
priv->subsys.kobj.ktype = &bus_ktype; /*设置读取总线属性文件的默认方法*/
priv->drivers_autoprobe = 1; /*驱动程序注册时,可以探测(probe)设备*/
retval = kset_register(&priv->subsys); /*注册总线容器 priv->subsys*/
if (retval) /*失败返回*/
goto out;
retval = bus_create_file(bus, &bus_attr_uevent);
/*建立 uevent 属性文件*/
if (retval) /**/
goto bus_uevent_fail;
/*创建一个 devices_kset 容器。也就是在新的总线目录下创建一个 devices 的目录,其
父目录就是 priv->subsys.kobj 对应的总线目录*/
priv->devices_kset = kset_create_and_add("devices", NULL,
&priv->subsys.kobj);
if (!priv->devices_kset) { /*创建失败则返回*/
retval = -ENOMEM;
goto bus_devices_fail;
}
/*创建一个 drivers_kset 容器。也就是在新的总线目录下创建一个 drivers 的目录,其
父目录就是 priv->subsys.kobj 对应的总线目录*/
priv->drivers_kset = kset_create_and_add("drivers", NULL,
&priv->subsys.kobj);
if (!priv->drivers_kset) { /*创建失败则返回*/
retval = -ENOMEM;
goto bus_drivers_fail;
}
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_
put); /*初始化设备链表*/
klist_init(&priv->klist_drivers, NULL, NULL); /*初始化驱动程序链表*/
retval = add_probe_files(bus); /*与热插拔相关的探测文件*/
if (retval)
goto bus_probe_files_fail;
retval = bus_add_attrs(bus); /*为总线创建一些属性文件*/
if (retval)
goto bus_attrs_fail;
pr_debug("bus: '%s': registered\n", bus->name);
return 0;
/*错误处理*/
bus_attrs_fail:
remove_probe_files(bus);
bus_probe_files_fail:
kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
kset_unregister(bus->p->devices_kset);
bus_devices_fail:
bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
kset_unregister(&bus->p->subsys);
kfree(bus->p);
out:
return retval;
}

Linux驱动开发7---设备驱动模型的三大组件相关推荐

  1. Linux 设备驱动开发 —— platform设备驱动应用实例解析

    前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 -- platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platfor ...

  2. <Linux开发>--驱动开发-- 字符设备驱动(3) 过程详细记录

    <Linux开发>–驱动开发-- 字符设备驱动(3) 过程详细记录 驱动开发是建立再系统之上的,前面作者也记录了系统移植的过程记录,如果有兴趣,可进入博主的主页查看相关文章,这里就不添加链 ...

  3. STM32MP157驱动开发——蜂鸣器设备驱动

    STM32MP157驱动开发--蜂鸣器设备驱动 0.相关知识 一.驱动程序开发 1.设备树修改 2.启动程序编写 3.测试程序编写 二.编译及运行测试 0.相关知识   蜂鸣器常用于计算机.打印机.报 ...

  4. STM32MP157驱动开发——platform设备驱动(中)

    STM32MP157驱动开发--platform设备驱动(中) 0.前言 一.platform设备模块--设备信息解析 二.platform驱动模块--加载设备 三.测试App 四.编译及运行 相关文 ...

  5. STM32MP157驱动开发——USB设备驱动

    STM32MP157驱动开发--USB设备驱动 一.简介 1.电气属性 2.USB OTG 3.STM32MP1 USB 接口简介 4.Type-C 电气属性 二.USB HOST 驱动开发 1.US ...

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

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

  7. Linux驱动开发|块设备驱动

    块设备驱动 块设备驱动是 Linux 三大驱动类型之一,块设备驱动比字符设备驱动复杂得多,不同类型的存储设备又对应不同的驱动子系统,下面介绍块设备驱动框架及使用 一.块设备介绍 块设备是针对存储设备的 ...

  8. linux的驱动开发——字符设备驱动

    1.字符设备驱动 \qquad字符设备驱动是最基本,最常用的设备.它将千差万别的硬件设备采用统一的接口封装起来,屏蔽了硬件的差异,简化了应用层的操作. 2.描述所有字符设备的结构体 \qquad描述所 ...

  9. I.MX6ULL ARM驱动开发---platfrom设备驱动

    引言   对IO进行最简单的读写操作,设备驱动都非常的简单.像I2C.SPI.LCD 等这些复杂外设的驱动就不能这么去写了,Linux 系统要考虑到驱动的可重用性,因此提出了驱动的分离与分层这样的软件 ...

  10. 正点原子-驱动开发-字符设备驱动

    Linux中的三大类驱动:字符设备.块和网络设备驱动 I2C.SPI.音频等都属于字符设备驱动 的类型 EMMC.NAND.SD卡和 U盘等存储都属于块设备 网卡,WIFI等都属于网络驱动 一个设备可 ...

最新文章

  1. 【springboot】【redis】springboot+redis实现发布订阅功能,实现redis的消息队列的功能...
  2. “元宇宙”概念引发AR/VR新一轮投资潮,去年Q4融资总额达120亿,超过此前2年总和...
  3. java网络流传输,中文乱码问题。
  4. 几何视角看线性方程组解的情况
  5. c#根据年份和月份获得本月最后一天
  6. 【Qt】2D绘图之绘制图像(二)
  7. Confluent官博:Kafka最牛队列,性能15倍于RabbitMQ!
  8. Mysql limit 子查询
  9. ELK套件FileBeat部署
  10. AVR Studio 5 使用初体验及完整版下载地址
  11. Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyExce
  12. Pandas 中第二好用的函数是?
  13. 后缀数组模板 hdu1403
  14. Windows下载FFmpeg最新版(踩了一上午的坑终于成功)
  15. 【SQL精彩语句】按某一字段分组取最大(小)值所在行的数据
  16. 弱引用什么时候被回收_Java中的强软弱虚引用
  17. mtk无线网卡 linux,在树莓派上使用基于MT7601的无线网卡(如360/百度/腾讯Wifi)
  18. 认识了解WMV 9 视频编解码器
  19. PMP 学习笔记 第8章 项目质量管理
  20. 基于Elasticsearch 实现站内全文搜索

热门文章

  1. 通过Python的pyttsx3库将文字转为音频
  2. tiny4412 busybox制作根文件系统rootfs nfs 挂载 ubuntu 14.04
  3. 难道是我对生活的要求过高了吗?
  4. 解决Ubuntu20.04远程桌面黑屏问题
  5. 《无人平台SLAM技术研究进展_王常虹》笔记
  6. Delsys表面肌电仪
  7. 核信号采集与数字化处理
  8. LED显示屏售后人员常用工具
  9. RF手机天线仿真介绍(三):调谐开关分析
  10. 传统洗护O2O平台纷纷溃败 智能洗衣会是他们的翻身的机会吗?