驱动开发硬核特训 · Day 13:从 device_create 到 sysfs,设备文件是如何生成的?


🔍

B站相应的视屏教程

📌 内核:博文+视频 - 备树深度解析:理论 + 实践全指南(含 of 函数与 i.MX8MP 实例)

敬请关注,记得标为原始粉丝。


🔧

📌 本文目标:深入理解 device_create() 函数的核心机制,搞清楚字符设备驱动中 /dev/xxx 是如何自动生成的,掌握 classdevicesysfsudev 之间的协作原理。本文面向 Linux 内核驱动开发初学者,全流程分析字符设备注册背后的关键路径,夯实设备模型的理解。


一、背景导入:为何要讲 device_create?

在我们编写 Linux 字符设备驱动时,经常会使用如下流程注册设备:

c 复制代码
alloc_chrdev_region();
cdev_init();
cdev_add();
class_create();
device_create(); // 核心

完成这些步骤后,系统会自动在 /dev/ 下生成对应设备节点,例如 /dev/my_led

但很多初学者会疑惑:

  • 为什么调用 device_create() 就能生成 /dev/xxx
  • 它是怎么和内核设备模型联系上的?
  • 它是否会注册 struct device
  • udev 又是什么关系?

本篇将一口气讲清楚这些问题。


二、设备模型再复习:class 是什么?

Linux 的设备模型中,class 是连接用户空间 /sys/class//dev/ 的关键中介,它代表某一类设备。

常见 class:

类别 描述 示例路径
tty 终端设备 /sys/class/tty/ttyS0
input 输入设备 /sys/class/input/event0
leds LED 灯控制 /sys/class/leds/user_led

你在驱动中调用:

c 复制代码
struct class *led_class = class_create(THIS_MODULE, "my_led_class");

内核会在 /sys/class/my_led_class/ 下创建一个新目录,为后续设备挂载做准备。

接下来进入主角------device_create()


三、device_create() 的功能与原型

3.1 函数原型

c 复制代码
struct device *device_create(struct class *class, struct device *parent,
                             dev_t devt, void *drvdata, const char *fmt, ...);

参数说明:

参数 含义
class 所属的 class(如 my_led_class)
parent 父设备,可为 NULL
devt 设备号,MKDEV(major, minor)
drvdata 设备私有数据,可用 device_get_drvdata 获取
fmt 设备名称格式,如 "my_led%d"

3.2 作用

执行 device_create() 会做三件事:

  1. 分配并注册一个新的 struct device
  2. 将其挂入 class,即:/sys/class/xxx/ 下出现新设备目录
  3. 通知 udev 创建 /dev/xxx 节点

这正是用户空间中能自动看到 /dev/my_led0 的原因。


四、完整流程梳理

我们通过一张图总结:

复制代码
驱动代码
└── device_create()
    ├── 创建设备结构体 struct device
    ├── 添加到 class 的设备列表
    │   └── 映射到 /sys/class/my_class/my_led0
    ├── 发出 uevent 通知
    │   └── 用户空间 udev 监听到设备加入事件
    │       └── 根据规则创建 /dev/my_led0

举个实际路径:

bash 复制代码
/sys/class/my_led_class/my_led0      # class 目录
/dev/my_led0                         # 实际设备节点(由 udev 创造)

五、实战演练:创建 LED 字符设备

5.1 初始化设备号

c 复制代码
dev_t devno;
alloc_chrdev_region(&devno, 0, 1, "my_led");
major = MAJOR(devno);

5.2 初始化 cdev

c 复制代码
cdev_init(&my_cdev, &my_fops);
cdev_add(&my_cdev, devno, 1);

5.3 创建设备 class 与 device

c 复制代码
my_class = class_create(THIS_MODULE, "my_led_class");
device_create(my_class, NULL, devno, NULL, "my_led0");

此时:

  • /sys/class/my_led_class/my_led0 被创建
  • /dev/my_led0 自动生成(由 udev 监听创建设备事件)

六、udev 的作用与补充说明

udev 是 Linux 中用户空间的设备管理守护进程。

  1. 它监听内核发出的设备事件(uevent
  2. 根据 /etc/udev/rules.d/ 的规则,执行创建设备节点、添加权限等操作

若系统中没有运行 udev(如部分嵌入式系统),需要用 mdev 或手动创建设备文件:

bash 复制代码
mknod /dev/my_led0 c 240 0

七、常见问题解答 Q&A

Q1:如果不调用 device_create(),是否还能访问设备?

可以,但必须自己创建设备节点:

bash 复制代码
mknod /dev/my_led0 c 240 0

并确保 major/minor 正确。但 /sys/class/ 等路径就不会自动生成。


Q2:多个设备如何创建多个节点?

你可以多次调用 device_create()

c 复制代码
device_create(my_class, NULL, MKDEV(240, 0), NULL, "my_led0");
device_create(my_class, NULL, MKDEV(240, 1), NULL, "my_led1");

这样就会生成 /dev/my_led0/dev/my_led1


Q3:如何自动清理?

在模块卸载时:

c 复制代码
device_destroy(my_class, MKDEV(240, 0));
class_destroy(my_class);
unregister_chrdev_region(MKDEV(240, 0), 1);

八、总结归纳

核心步骤 功能
class_create 创建设备类别,挂载到 /sys/class
device_create 注册 struct device,生成 /sys 和 /dev 节点
udev 监听内核事件,自动创建设备文件
dev_set_drvdata 设置私有数据,可用 device_get_drvdata 获取
cdev 操作 管理字符设备的核心操作结构

九、今日练习题(建议动手)

  1. 编写一个字符设备驱动,支持创建两个设备节点 /dev/led0/dev/led1
  2. 分别用 write() 控制两个设备状态,打印开关日志
  3. 使用 udevadm monitor 查看 device_create() 时产生的事件

📌 下一篇预告:

驱动开发硬核特训 · Day 14:深入理解 class、device 与 /dev 的完整链路

将进一步拆解 class.c 源码,讲清 device_add()kobject 关系,帮助你彻底掌握设备文件生成机制。


如果这篇内容帮助到你,欢迎点赞、收藏、转发!

📺 B站:嵌入式Jerry

📘 CSDN 博客:嵌入式Jerry

👉 下一篇,见!

相关推荐
天夏已微凉1 小时前
OpenHarmony系统HDF驱动开发介绍(补充)
驱动开发·音视频·harmonyos
不摆烂选手16 小时前
Linux 阻塞和非阻塞 I/O 简明指南
linux·驱动开发·ubuntu·正点原子imx6ull学习笔记
__Benco19 小时前
OpenHarmony平台驱动开发(十五),SDIO
驱动开发
7yewh20 小时前
FPGA前瞻篇-计数器设计与实现实例
arm开发·驱动开发·嵌入式硬件·fpga开发·硬件架构·硬件工程·精益工程
程序员JerrySUN1 天前
《驱动开发硬核特训 · 专题篇》:深入理解 I2C 子系统
驱动开发
sukalot1 天前
window 显示驱动开发-将虚拟地址映射到内存段(二)
驱动开发
忧虑的乌龟蛋2 天前
嵌入式Linux I2C驱动开发详解
linux·驱动开发·嵌入式·iic·i2c·读数据·写数据
月上柳青2 天前
linux-驱动开发之设备树详解(RK平台为例)
linux·驱动开发·dsp开发
程序员JerrySUN3 天前
驱动开发硬核特训 · Day 30(下篇): 深入解析 lm48100q I2C 音频编解码器驱动模型(基于 i.MX8MP)
linux·驱动开发·架构·音视频
Blossom.1184 天前
《从零开始:构建你的第一个区块链应用》
人工智能·驱动开发·python·深度学习·区块链·aigc·交互