当前位置: 首页 > news >正文

驱动开发硬核特训 · Day 10 (理论上篇):设备模型 ≈ 运行时的适配器机制

🔍

B站相应的视屏教程
📌 内核:博文+视频 - 总线驱动模型实战全解析
敬请关注,记得标为原始粉丝。


在 Linux 驱动开发中,设备模型(Device Model)是理解驱动架构的核心。而从软件工程的角度看,它与**适配器模式(Adapter Pattern)**之间也存在着惊人的相似性。本文尝试从理论出发,构建“设备模型 ≈ 运行时的适配器机制”的认知,并通过逻辑图与结构分析,将这一理念讲透讲透。


一、适配器模式回顾:统一接口的桥梁

在这里插入图片描述

在软件设计模式中,**适配器模式(Adapter Pattern)**的作用是:将一个类的接口转换成客户端所期待的另一个接口

  • 目标接口(Target):客户端期待调用的接口
  • 源接口(Adaptee):已有的但不兼容的接口
  • 适配器(Adapter):中间桥梁,让客户端可以透明使用源接口

我们以 USB 转串口为例:

Client(PC) <--> USB接口
                ↓ 适配器
设备(串口芯片) <--> UART接口

在代码中,Adapter 就是包装 Adaptee 的对象,让它“看起来”满足了 Target 接口。


二、Linux 设备模型的运行时角色

Linux 的设备模型其实也完成了“统一接口”的桥接动作:

  • platform_device / i2c_client 等设备描述结构(相当于 Adaptee)
  • platform_driver / i2c_driver 等驱动结构(相当于 Adapter)
  • driver core(驱动核心)通过总线匹配机制连接设备与驱动(Adapter 注册给一个 Bus,用于查找匹配)

当你写下如下代码时:

platform_driver_register(&my_driver);

实际上就是在告诉内核:我有一个驱动,它能适配某些符合匹配条件的设备,请你在运行时自动“配对”他们。

这正是“运行时适配器机制”的体现!


三、匹配机制的本质:驱动适配器为谁服务?

1. 核心概念类比:

软件工程术语Linux 设备模型
Target接口驱动模型中的标准接口(probe等)
Adaptee类各种硬件设备(platform、I2C等)
Adapter适配器驱动结构体(platform_driver等)
适配者注册driver_register / i2c_add_driver
自动装配匹配逻辑总线匹配函数(of_match、id_table)

2. 匹配的流程图:

           ┌────────────┐
           │ 设备树Node │  ←──── 用户定义设备信息
           └────┬───────┘
                │
                ▼
         ┌──────────────┐
         │ platform_device │ ←─── 内核解析设备树,注册
         └────┬──────────┘
              │
              ▼
         ┌──────────────┐
         │  platform_bus │ ←─── 总线负责配对逻辑
         └────┬──────────┘
              │
      probe匹配机制
              │
              ▼
         ┌──────────────┐
         │ platform_driver │ ←── 驱动是适配器
         └──────────────┘

四、为什么说它是“运行时”的适配器?

适配器模式在传统软件设计中通常是编译期设计好适配关系,但在 Linux 驱动中,设备与驱动的绑定是:

  • 在设备注册(如 platform_device)后,在 driver core 的设备链表中查找驱动
  • 或者在驱动注册后,从已知设备中查找与之匹配的设备
  • 依据的是 名字匹配 / compatible 字符串

因此,这是 运行时动态匹配与绑定,它不是写死的关系,而是通过总线模型中的匹配函数灵活控制。


五、多个总线的统一模型:都是适配器

我们常见的 driver 类型:

  • platform_driver
  • i2c_driver
  • spi_driver
  • usb_driver
  • pci_driver

它们都继承了一个共同的父结构:

struct device_driver {
    const char *name;
    struct bus_type *bus;
    ...
};

它们都注册给对应的 bus_typebus_type 就是 Adapter 插口类型的定义者

换句话说,不同总线驱动之间的差异只是适配规则的差异,核心逻辑是一样的:我声明我能处理什么设备(通过 compatible 或 ID 表),然后内核会自动调用 probe 函数完成初始化。


六、设备模型中的三大核心角色

为了理解更深入,我们整理出设备模型三大核心结构体的适配关系:

设备模型角色软件设计模式对应Linux结构体功能描述
被适配者Adapteeplatform_device / i2c_client硬件描述
适配器Adapterplatform_driver / i2c_driver驱动逻辑
适配管理器AdapterManagerbus_type匹配规则、注册匹配与解绑回调

这三者构成了一个完整的“运行时适配”生态。


七、适配器模式的优势在驱动模型中的体现

适配器优势驱动模型的体现
将不兼容接口统一包装硬件种类繁多,统一由 driver core 适配
解耦:客户端与底层对象分离用户只关心 probe 中的行为,与具体设备解耦
支持运行时灵活绑定动态添加/删除驱动与设备都是天然支持的

八、真实场景举例:平台驱动模型

假设你有如下设备树片段:

lcdif1: lcd-controller@32e80000 {
    compatible = "fsl,imx8mp-lcdif1";
    reg = <0x32e80000 0x10000>;
    interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
    ...
};

你注册了如下 platform_driver:

static const struct of_device_id lcdif_match[] = {
    { .compatible = "fsl,imx8mp-lcdif1" },
    { /* sentinel */ }
};

static struct platform_driver lcdif_driver = {
    .probe = lcdif_probe,
    .remove = lcdif_remove,
    .driver = {
        .name = "lcdif",
        .of_match_table = lcdif_match,
    },
};

整个过程就是典型的 运行时适配器匹配:设备为 Adaptee,驱动为 Adapter,由 bus_type 来桥接匹配


九、总结与过渡

我们可以得出核心观点:

Linux 的驱动模型不是传统静态接口封装,而是构建了一个运行时的适配器机制系统,通过 bus / device / driver 三者的动态配对完成模块化的解耦架构。

  • 驱动 ≈ Adapter
  • 总线 ≈ AdapterManager(匹配策略)
  • 设备 ≈ Adaptee
  • probe 函数 ≈ Target 接口执行器

下一篇内容将全面深入 platform_driver、i2c_driver 结构与实际设备树如何映射为设备对象,驱动如何实现匹配,sysfs 如何生成等具体实现细节,并围绕 PCA9450 PMIC 进行实战代码分析。

敬请期待 Day 10 博文下篇:《设备模型 ≈ 运行时的适配器机制(下)——以 V4L2 摄像头驱动为例》


相关文章:

  • c++中的this
  • 用java代码如何存取数据库的blob字段
  • 02 - spring security基于配置文件及内存的账号密码
  • 设计模式 --- 访问者模式
  • 【LeetCode】算法详解#4 ---合并区间
  • 进程线程回顾
  • Pinia最基本用法
  • Nginx基础讲解
  • ros2-rviz2控制unity仿真的6关节机械臂,探索从仿真到实际应用的过程
  • 论文精度:HeightFormer:基于Transformer的体素高度预测在路边3D目标检测中的应用
  • flutter 桌面应用之右键菜单
  • 【Cursor 】Cursor 安装与配置指南:从零开始的高效开发之旅
  • QT6 源(16):存储 QT 里元对象的类信息的类 QMetaClassInfo 的类,只有两个成员函数 name()、value(),比元对象属性简单多了
  • 数据驱动,数字能量分析API助力手机号数据解读
  • RAG Fusion技术详解与应用场景
  • 趣味编程之Spring的白学之路
  • 二、Android Studio环境安装
  • [React] 如何用 Zustand 构建一个响应式 Enum Store?附 RTKQ 实战与 TS 架构落地
  • 波束形成(BF)从算法仿真到工程源码实现-第七节-关于波束10个基本概念
  • Jenkins 发送钉钉消息
  • 九江银行落地首单畜牧业转型金融业务,助推传统农业绿色智能
  • 中国田径巡回赛西安站完赛:男子跳远石雨豪夺冠,女子跳高刘肼毅折桂
  • 读懂城市|成都高新区:打造“人尽其才”的“理想之城”
  • 商务部:对原产于美国、欧盟、台湾地区和日本的进口共聚聚甲醛征收反倾销税
  • 柬埔寨果农:期待柬埔寨榴莲走进中国市场
  • 《歌手》回归,人均技术流,00后整顿职场