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

驱动开发硬核特训 · Day 19:从字符设备出发,掌握 Linux 驱动的实战路径(含 gpio-leds 控制示例)

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

一、背景说明:字符设备驱动的角色定位

在 Linux 内核驱动体系中,**字符设备驱动(Character Device Driver)**扮演着关键的桥梁作用,它直接向用户空间程序提供 read/write/ioctl 等接口,适用于键盘、LED、GPIO、串口等多类设备。而在日常的嵌入式开发中,我们往往会面对一个核心问题:

“设备树已经定义了硬件设备,子系统(比如 gpio-leds)也帮我点亮了 LED,为何还要写字符设备驱动?”

本篇博文将围绕这个问题,逐步展开,从设备模型 → 子系统 → 字符设备驱动之间的逻辑关系梳理,再深入实践,完成一个基于 i.MX8MP 平台的 LED 控制字符设备驱动,掌握字符设备的创建、注册与用户空间控制。


在这里插入图片描述

二、核心概念回顾:设备模型、子系统与字符设备的关系

2.1 设备模型(Device Model)

Linux 内核的设备模型为设备、驱动和总线之间的关系建立了统一的框架:

  • struct device:表示一个实际设备;
  • struct device_driver:对应驱动;
  • struct bus_type:设备与驱动的桥梁。

所有设备都要在 device model 下注册,但设备模型 本身不提供功能接口,它只建立了设备的逻辑与生命周期。


2.2 子系统(Subsystem)

子系统是在设备模型基础上的功能分类,如:

  • input 子系统:键盘、触摸屏;
  • block 子系统:磁盘;
  • tty 子系统:串口;
  • gpio-leds 子系统:LED 控制。

子系统的出现解放了开发者,某些简单设备无需写驱动,只要配置设备树即可,例如 gpio-leds 自动帮你注册 LED class device,并在 /sys/class/leds 下生成节点,支持用户空间直接操作。

但问题来了:

如果我们需要通过 write() 等方式直接从应用控制 LED 呢?

这就要用到:


2.3 字符设备驱动(Character Device Driver)

字符设备驱动负责建立 /dev/mydev 这样的接口,实现 file_operations 结构体,从而让用户空间通过 open/read/write 与内核驱动打交道。它是最基础、最灵活的驱动方式。


三、问题提出:gpio-leds 为何无法直接与字符设备结合?

以设备树片段为例(位于 imx8mp-evk.dts):

gpio-leds {compatible = "gpio-leds";pinctrl-names = "default";pinctrl-0 = <&pinctrl_gpio_led>;status {label = "yellow:status";gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>;default-state = "on";};
};

系统自动生成 /sys/class/leds/yellow:status/brightness 节点,我们可:

echo 1 > /sys/class/leds/yellow:status/brightness  # 点亮
echo 0 > /sys/class/leds/yellow:status/brightness  # 熄灭

但此类节点仅通过 sysfs 接口工作,并未与 /dev/ledchar 之类的字符设备产生映射关系


四、实战:为 gpio-leds 控制引入字符设备接口

我们以 gpio3_16(GPIO 编号为 32 * 2 + 16 = 80)为例,构造一个最小的字符设备驱动模块。

4.1 驱动代码

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <linux/cdev.h>
#include <linux/device.h>#define GPIO_NUM 80  // 对应 gpio3_16
static dev_t devt;
static struct cdev cdev;
static struct class *led_class;static ssize_t led_write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{char kbuf[4];if (copy_from_user(kbuf, buf, len))return -EFAULT;gpio_set_value(GPIO_NUM, kbuf[0] == '1' ? 1 : 0);return len;
}static struct file_operations led_fops = {.owner = THIS_MODULE,.write = led_write,
};static int __init led_dev_init(void)
{gpio_request(GPIO_NUM, "led_gpio");gpio_direction_output(GPIO_NUM, 1);alloc_chrdev_region(&devt, 0, 1, "led_char");cdev_init(&cdev, &led_fops);cdev_add(&cdev, devt, 1);led_class = class_create(THIS_MODULE, "led_class");device_create(led_class, NULL, devt, NULL, "ledchar");pr_info("ledchar device initialized\n");return 0;
}static void __exit led_dev_exit(void)
{gpio_set_value(GPIO_NUM, 0);gpio_free(GPIO_NUM);device_destroy(led_class, devt);class_destroy(led_class);cdev_del(&cdev);unregister_chrdev_region(devt, 1);
}module_init(led_dev_init);
module_exit(led_dev_exit);
MODULE_LICENSE("GPL");

4.2 编译与测试

编译为模块:

obj-m += ledchar.o

加载模块:

insmod ledchar.ko

用户空间控制:

echo 1 > /dev/ledchar   # 点亮
echo 0 > /dev/ledchar   # 熄灭

五、总结对比:sysfs 与字符设备的协作与区别

方式适用场景优势劣势
sysfs接口自动生成的 class 设备无需写驱动,通用接口单一,不支持复杂逻辑
字符设备精细控制 / 用户接口可定义多操作 / 定制协议需自行注册,开发成本略高
两者结合桥接通用与专用可在 sysfs 生成节点 + 自定义更强大但设计复杂

在一些复杂场景(如 SPI 设备、定制协议、UI 控制等)中,字符设备几乎不可替代。


六、延伸思考:如何从子系统向字符设备扩展?

未来开发中,建议按如下路径深入:

  1. 明确内核已支持的子系统是否能满足需求
  2. 通过 class_create + cdev_add 绑定字符设备接口
  3. 使用 udev 自定义 /dev 节点自动创建设备文件
  4. 编写自定义 ioctl 进行配置交互(可参考 camera/v4l2)

七、写在最后

本节通过一个实战示例,深入讲解了:

  • 设备树中的 gpio-leds 与字符设备的区别;
  • 如何构造字符设备驱动访问 GPIO;
  • sysfs 与 /dev 的本质差异。

我们将在下一节中进一步引入 ioctl 控制方法,让字符设备驱动更具交互能力。


每日一句:不要轻视字符设备,它是所有复杂驱动的起点。


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

相关文章:

  • oralce 查询未提交事务和终止提交事务
  • [特殊字符]️ 基于Pytest的自动化测试框架架构解析
  • 不要使用Round函数保留小数位了
  • 【问题】解决docker的方式安装n8n,找不到docker.n8n.io/n8nio/n8n:latest镜像的问题
  • RocketMQ事务消息详解
  • c#-命名和书写规范
  • Java虚拟机(JVM)家族发展史及版本对比
  • C语言之阶乘2.0
  • H3C Magic路由器安全警报来啦![特殊字符][特殊字符]
  • uniapp 仿小红书轮播图效果
  • 深度解析 TransmittableThreadLocal(TTL):原理、实战与优化指南
  • Node.js 学习入门指南
  • Linux 内核 IPv4 套接字创建机制与协议表管理深度解析
  • 全链路数据仓建设指南:从构建流程到应用场景
  • 银河麒麟系统安装vscode
  • 2023 国考
  • JAVA中包装类型的数值比较问题
  • SPH Engineering - 无人机技术开发专家
  • shell脚本2
  • k8s基于角色的访问控制(RBAC)
  • “五一”前多地市监部门告诫经营者:对预订客房不得毁约提价
  • 复旦大学校友夫妇一次性捐赠10亿元,成立学敏高等研究院
  • 山东省检察院答澎湃:惩治网络售假,强化“全链条”刑事打击
  • 港澳航天员最早2026年飞天
  • 董明珠连任格力电器董事,回应管理层年轻化
  • 柬埔寨人民党中央外委会副主席:柬中友谊坚如钢铁,期待更多合作