Linux设备驱动框架设计

引子

Linux操作系统的一大优势就是支持数以万计的芯片设备,大大小小的芯片厂商工程师都在积极地向Linux kernel提交设备驱动代码。能让这个目标得以实现,这背后隐藏着一个看不见的技术优势:Linux内核提供了一套易于扩展和维护的设备驱动框架。Linux内核本身提供一套设备驱动模型,此模型提供了Linux内核对设备的一般性抽象描述,包括设备的电源管理、对象生命周期管理、用户空间呈现等等。在设备模型的帮助下,设备驱动开发工程师从设备的一般性抽象中解脱出来。但是每个设备的具体功能实现还需要大量开发工作,如果每个设备都从头开发,那工作量无疑相当巨大。而这些设备可以按功能进行分类,每个设备类在业界或者标准组织中定义了硬件标准规范,所以针对每个设备类,如果有一个针对此设备类的功能性抽象框架,这将大大加快新设备的添加和开发效率。设备标准规范的存在,无疑对设备驱动框架的设计提供了有力的支撑。

但是坏消息也不少:

  1. 标准规范往往落后于产品,特别对新兴设备来说。
  2. 一个设备类可能是一套标准规范定义,也有可能是多套标准规范定义。
  3. 芯片厂商之间,为了达到提升自己的技术优势、市场壁垒等目的,在标准规范之内或之外,做了很多vendor specific的实现。

这些差异性需求下,一个设备类就像一颗树,其树干为设备标准规范(可能有多个,如下图),每个分支为厂商设备类或设备子类规范,而每片树叶就是每个具体的设备。设备框架的目的就是能帮助驱动工程师简洁优雅地添加一片树叶。这些差异性需求对框架设计是一个不小的挑战,如何很好地支持这些需求,是考验优秀设备驱动框架的试金石。

本文的目的就是总结一些内核设备驱动框架的优秀设计方案,以供大家参考。如有疏漏,也欢迎大家留言补充。

ATA设备驱动框架设计

现状描述

ATA驱动模块管理众多的SATA、PATA设备。以SATA设备为例,又分支持和不支持 port multiplier功能的,支持port multiplier的。而且SATA总线又存在多种标准规范定义的(ahci、fsl、 sil24 etc.),就算是用ahci 总线标准的,有些厂商总在某些地方做的跟标准不一致。

设计要点

  • 所有功能点抽象成接口,再抽象成数据结构struct ata_port_operations,实现对象的多态;
  • 通过struct ata_port_operations的inherits字段实现对象的继承;
  • 新的设备驱动添加,就是添加新的struct ata_port_operations对象,而此对象可以从已有的相似对象节点上,通过inherits字段继承大部分的功能。

框架设计相关代码示例:

单板控制领域模型设计与实现》采用此驱动框架设计开发。

PMBus设备驱动框架设计

现状描述

PMBus有一套标准规范,其中有些是基本功能,有些是可选功能。基本功能是必须要实现的,而且寄存器接口也进行标准化。而可选功能由各设备厂商自由决定,而且这些可选功能的寄存器接口也无统一规范,支持PMBus设备厂商的自定义寄存器。

设计要点

  • 通过struct pmbus_data对pmbus设备进行抽象性描述,此对象聚合对象pmbus_driver_info和pmbus_sensor。通过struct pmbus_driver_info对pmbus设备标准规范进行抽象性描述,struct pmbus_sensor对pmbus传感器进行抽象性描述。
  • 可选功能集通过pmbus_driver_info的u32 func[PMBUS_PAGES]字段描述。
  • 非标准寄存器通过虚拟寄存器(Virtual registers)统一到pmbus驱动框架中。虚拟寄存器到设备自定义寄存器的映射通过pmbus_driver_info的4个接口:read_byte_data/read_word_data/write_word_data/write_byte来完成。 
  • 所以当添加一个新设备时,其差异性需求都封装在pmbus_driver_info中,这样pmbus_data和pmbus_sensor做为公共功能则无需修改,
  • 通过构造新的pmbus_driver_info对象即可完成新的设备驱动的添加。

框架设计相关代码示例:

linux PMBus总线及设备驱动分析》是对PMBus设备的进一步介绍。  

 USB块设备驱动框架设计

现状描述

USB块设备有一套标准规范定义,但USB设备类型众多(如U盘、MP3播放器、手机、GPS设备等等),各厂商水平参差不齐,实现混乱。而且因为USB规范相对较新,一直在演进变化中,这也加剧了这一混乱。比如:

  • 设备描述符中subclass、protocol字段为空或者不正确;
  • 应答sense长度非标准;
  • INQUIRY设备请求非标准;
  • bulk传输协议中的 tag 不匹配;
  • 类似问题近20个

另外,Linux内核已有一套通用的SCSI块设备驱动框架,如果USB块设备能复用这个框架,那是一个最好的选择。

设计要点

  • 通过struct scsi_host_template对scsi块设备进行抽象性描述,USB块设备通过创建一个scsi_host_template对象,集成到SCSI块设备驱动框架中;
  • 通过struct us_data对USB块设备进行抽象性描述,通过us_data的fflags字段和unusual_dev字段对USB块设备中的非标准行为进行抽象性描述;
  • 通过struct usb_device_id对USB块设备vendor-specific属性进行抽象描述,这样通过添加一个新的usb_device_id实例,即可完成对一个新的USB块设备驱动的添加。

框架设计相关代码示例:

  

posted @   wahaha02  阅读(4616)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示