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

理解字符设备、设备模型与子系统:以 i.MX8MP 平台为例

视频教程请关注 B 站:“嵌入式 Jerry”


Linux 内核驱动开发中,很多人在接触字符设备(char device)、设备模型(device model)和各种子系统(subsystem)时,往往会感到概念混杂,边界模糊。本文将从 Linux 驱动体系架构的演化入手,结合 NXP 的 i.MX 8M Plus EVK 平台(下文简称 i.MX8MP-EVK),深入讲解这三者的关系、用途与实际代码的融合方式,帮助你彻底理解这些核心概念。


在这里插入图片描述

一、历史与基础概念

1.1 字符设备(Character Device)

字符设备是 Linux 设备类型之一,另一种是块设备(Block Device)。字符设备以字节为单位进行读写,接口类似于普通文件,通过 read()write()ioctl() 等系统调用进行操作。

  • 常见字符设备:串口(serial)、GPIO、I2C、PWM、Watchdog 等。
  • 管理结构:主要由 struct file_operationsstruct cdev 控制,最终通过 register_chrdev_region()cdev_add() 注册到系统。

1.2 设备模型(Device Model)

Linux 为了实现设备与驱动的自动匹配、热插拔管理、sysfs 显示,设计了一套统一的设备模型架构,包括以下关键结构:

  • struct device
  • struct driver
  • struct bus_type
  • struct class

这套模型抽象了“设备是如何插到系统里的、驱动如何找到设备、如何在用户空间体现出设备结构”等问题。

设备模型的意义在于:“它是一种运行时的驱动与设备匹配与管理框架”。

1.3 子系统(Subsystem)

“子系统”是指内核中具有统一接口规范的功能模块,例如:

  • I2C 子系统
  • SPI 子系统
  • PWM 子系统
  • regulator 子系统
  • input 子系统
  • sound 子系统

每个子系统背后都有一个核心的框架代码,并暴露出标准接口(如 struct pwm_chipstruct i2c_driver 等),驱动开发者按照接口标准进行设备适配即可。

子系统的意义在于:“统一了设备驱动的行为规范和上层调用方式,是设备模型的具体实现与应用场景”。


二、三者关系的准确理解

我们通过一个类比来帮助你理解三者关系:

类别类比解释实际作用
字符设备老式收音机,直接接电可用最基本的驱动编程方式
设备模型家庭电网管理系统让每台收音机能统一开关、统一命名、自动识别
子系统不同的电台频道系统(如 FM/AM)为收音机统一音频标准接口、设置方法等

正确理解:

  • 设备模型并不是“设备驱动的替代品”,而是驱动与设备的匹配系统。
  • 字符设备可裸用,也可嵌入子系统内部。
  • 子系统是专用领域的模型扩展,基于设备模型构建的统一抽象。

三、实战解析:以 i.MX8MP 的 PWM 驱动为例

NXP 的 pwm-imx27 驱动是一个非常典型的子系统 + 设备模型驱动的代表。下面我们从设备树、驱动代码到字符接口逐步解析。

3.1 设备树定义(设备描述)

arch/arm64/boot/dts/freescale/imx8mp-evk.dts 中:

&pwm1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_pwm1>;status = "okay";
};

说明:pwm1 控制器启用,绑定了特定管脚。

3.2 驱动注册过程(platform_device + pwm_chip)

驱动源码文件:drivers/pwm/pwm-imx27.c

注册入口:

static struct platform_driver imx_pwm_driver = {.driver = {.name = "pwm-imx27",.of_match_table = pwm_imx27_dt_ids,},.probe = pwm_imx27_probe,
};
module_platform_driver(imx_pwm_driver);

核心结构:

struct pwm_imx27_chip {struct pwm_chip chip; // 属于PWM子系统的驱动注册入口...
};

pwm_chip 是子系统定义的结构体,其 ops 字段中定义了 .apply.get_state 等操作接口。

然后调用:

return devm_pwmchip_add(&pdev->dev, &imx->chip);

此函数实际上完成了驱动注册到子系统 + 注册 sysfs 接口 + device model 挂载等多个功能。

3.3 sysfs 与字符设备的区别

尽管 pwm-imx27 没有 register_chrdevcdev_add,但它通过子系统自动创建了 sysfs 接口,例如:

/sys/class/pwm/pwmchip0/

这意味着控制 PWM 不再依赖传统字符设备节点 /dev/pwm0,而是通过标准 pwm 子系统提供的统一 sysfs 文件操作。


四、对比分析:没有子系统的字符设备

若驱动不走子系统,例如传统的 LED 控制驱动,则需要手动注册字符设备:

register_chrdev_region();
cdev_init();
cdev_add();

并创建 /dev/xxx 节点,再通过 open/read/write/ioctl 实现访问。

优缺点对比

特性传统字符设备子系统驱动(如 PWM)
注册方式register_chrdev + cdevpwmchip_add 等
用户访问方式/dev/xxxsysfs + standard API
是否自动匹配设备
是否统一接口
开发复杂度中等略高(但标准)

五、设备模型:驱动背后的系统机制

Linux 驱动之所以能做到自动识别设备、按需加载驱动,靠的就是设备模型架构。

5.1 总线(bus_type)

  • platform 总线:用于板载设备(PWM、I2C、SPI)
  • usb 总线:用于外设热插拔设备
  • pci 总线:用于 PC 设备识别与枚举

所有子系统最终都依赖某种 bus 类型与设备模型框架。

5.2 匹配过程(match)

设备模型按照:

  • .of_match_table(设备树匹配)
  • .id_table(非设备树匹配)

来完成 devicedriver 的自动匹配与调用 probe。


六、结语与建议

6.1 学习建议

  • 新手建议从字符设备入手,理解基础接口。
  • 进阶阶段要深入了解设备模型与 sysfs 接口。
  • 若目标是嵌入式设备驱动,应熟练掌握子系统开发接口(如 I2C/SPI/PWM 等子系统结构)。

6.2 总结结构图

           +------------------------+|     用户空间接口       |+------------------------+↑+-------------------------+|     sysfs / /dev 节点    |+-------------------------+↑+----------------------------+|  子系统接口(如 PWM/SPI)   |+----------------------------+↑+---------------------------+|  设备模型(device model) |+---------------------------+↑+--------------------------+|   platform/PCI/... bus   |+--------------------------+

附录:i.MX8MP 平台相关驱动推荐阅读

  • drivers/pwm/pwm-imx27.c:PWM 控制器驱动
  • drivers/regulator/pca9450-regulator.c:PMIC 驱动
  • drivers/i2c/busses/i2c-imx.c:I2C 控制器驱动

视频教程请关注 B 站:“嵌入式 Jerry”

http://www.xdnf.cn/news/75979.html

相关文章:

  • [U-Net-Dual]DEU-Net
  • 【上海大学数据库原理实验报告】MySQL数据库的C/S模式部署
  • WebRTC服务器Coturn服务器相关测试工具
  • 什么事Nginx,及使用Nginx部署vue项目(非服务器Nginx压缩包版)
  • 力扣2685(dfs)
  • 桌面我的电脑图标不见了怎么恢复 恢复方法指南
  • docker保存镜像到本地
  • 懒人一键搭建符号执行环境V5K3
  • 【VS Code】打开远程服务器Docker项目或文件夹
  • Dataway在Spring Boot中的引入以及使用教程
  • 【美化vim】
  • Element Plus表格组件深度解析:构建高性能企业级数据视图
  • 【C++ 类和数据抽象】构造函数
  • 智能体MCP 实现数据可视化分析
  • Java 安全:如何防止 SQL 注入与 XSS 攻击?
  • GAEA的技术优势:分层加密与去中心化数据治理
  • 《C++ 模板:泛型编程的核心》
  • 基于javaweb的SSM+Maven小区失物招领系统设计与实现(源码+文档+部署讲解)
  • 超越Dify工作流:如何通过修改QwenAgent的Function Call及ReAct方法实现对日期时间的高效意图识别
  • 【MySQL】005.MySQL表的约束(上)
  • 2011-2020年 上市公司彭博ESG综合得分、环境得分、​治理得分统计数据表
  • Ollama 实战手册
  • 软考软件设计师考试情况与大纲概述
  • 【C语言】初阶算法相关习题(一)
  • Docker 部署 PostgreSQL 数据库
  • 记录学习的第三十天
  • 20.4 显示数据库数据
  • Centos 、Linux 基础运维命令
  • 【程序员 NLP 入门】词嵌入 - 如何基于计数的方法表示文本? (★小白必会版★)
  • MacOS 10.15上能跑大语言模型吗?