驱动开发硬核特训 · Day 21(上篇加强版):深入理解子系统机制与实战初探

📅 日期:2025-04-27
📚 技术平台:嵌入式Jerry(B站)


1. 为什么要有子系统?(深度版)

在 Linux 内核发展早期,设备管理较为混乱,每种设备(如网卡、硬盘、LED)各自为政,驱动开发非常困难,系统维护复杂、扩展困难。

在这里插入图片描述

1.1 难点总结

  • 接口不统一:每类设备定义自己的操作方式
  • 用户访问混乱:无法通过统一路径管理设备
  • 内核膨胀严重:各种 if-else、switch-case 代码横行

1.2 子系统带来的变化

✅ 为每一类功能设备定义 统一接口规范
✅ 在 /sys/class/ 下暴露出 统一访问路径
✅ 驱动开发者只需遵循子系统接口,避免重复设计
✅ 设备热插拔、动态加载、统一管理变得简单。


2. 子系统本质是什么?

一句通俗的话:

子系统是内核根据设备功能,把一大堆设备分类管理的机制。

技术上:

  • 基于 kobject/kset/ktype 的设备模型机制
  • 在 sysfs 文件系统中形成 class 目录
  • 提供标准的注册/注销流程

2.1 子系统 VS 设备模型

项目设备模型 (device model)子系统 (subsystem)
定义Linux 内核通用框架特定类型设备的组织分类
基础kobject/kset/ktype基于设备模型构建
目的支撑总线/驱动/设备统一管理便于管理一类设备
示例platform bus, devicenet, block, regulator

3. 子系统的基本结构和机制

一个子系统通常包括:

  • Class:对应 sysfs 的 /sys/class/,逻辑分组
  • Device:每个实例(一个 LED、一个 BUCK)对应一个 device
  • Driver:驱动设备,通常与特定 bus 匹配

结构图理解:

class_create() -> 创建类 (Class)
device_create() -> 创建设备 (Device)

用户空间访问:
/sys/class/<class>/<device>/

4. 子系统创建与使用详细流程

4.1 创建子系统

内核代码核心步骤:

// 1. 创建一个 Class(子系统)
struct class *my_class;

my_class = class_create(THIS_MODULE, "mychar_class");
if (IS_ERR(my_class))
    return PTR_ERR(my_class);

对应生成 /sys/class/mychar_class/


4.2 注册设备到子系统

// 2. 在子系统下挂一个设备
struct device *dev;

dev = device_create(my_class, NULL, devt, NULL, "mychar");
if (IS_ERR(dev))
    return PTR_ERR(dev);

对应生成 /sys/class/mychar_class/mychar 节点。

同时,udev等工具可自动生成 /dev/mychar 设备文件。


4.3 销毁流程

// 卸载时销毁
device_destroy(my_class, devt);
class_destroy(my_class);

确保模块退出时资源清理,防止内核内存泄漏。


5. 详细实例:基于 i.MX8MP EVK 控制 LED

5.1 设备树节点

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";
    };
};

说明:

  • GPIO3_16 = 32 * 2 + 16 = 80号 GPIO
  • 默认状态点亮

5.2 驱动代码示例(增加丰富注释版)

#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 LED_GPIO 80  // gpio3_16

static dev_t devt;
static struct cdev led_cdev;
static struct class *led_class;
static struct device *led_device;

// 写接口,实现开关LED
static ssize_t led_write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
    char kbuf[4] = {0};
    if (copy_from_user(kbuf, buf, len))
        return -EFAULT;

    if (kbuf[0] == '1')
        gpio_set_value(LED_GPIO, 1); // 点亮
    else
        gpio_set_value(LED_GPIO, 0); // 熄灭

    return len;
}

// 文件操作结构
static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .write = led_write,
};

static int __init led_init(void)
{
    int ret;

    // 申请GPIO
    ret = gpio_request(LED_GPIO, "led_gpio");
    if (ret)
        return ret;

    gpio_direction_output(LED_GPIO, 1);

    // 分配设备号
    alloc_chrdev_region(&devt, 0, 1, "ledchar");
    cdev_init(&led_cdev, &led_fops);
    cdev_add(&led_cdev, devt, 1);

    // 创建子系统(class)
    led_class = class_create(THIS_MODULE, "led_class");
    led_device = device_create(led_class, NULL, devt, NULL, "ledchar");

    pr_info("ledchar device initialized\n");
    return 0;
}

static void __exit led_exit(void)
{
    gpio_set_value(LED_GPIO, 0);
    gpio_free(LED_GPIO);

    device_destroy(led_class, devt);
    class_destroy(led_class);
    cdev_del(&led_cdev);
    unregister_chrdev_region(devt, 1);

    pr_info("ledchar device removed\n");
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

5.3 加载模块效果

# 加载模块
insmod ledchar.ko

# 查看/sys目录
ls /sys/class/led_class/ledchar/

# 控制LED
echo 1 > /dev/ledchar
echo 0 > /dev/ledchar

✅ 通过字符设备 /dev/ledchar 写操作,控制真正硬件上的 GPIO 灯亮灭。
✅ 同时在 /sys/class/led_class/ledchar/ 中可查看设备属性。


6. 深度讲解:子系统、字符设备、设备模型关系总结

类型作用示例本质
字符设备 (cdev)提供read/write/ioctl接口/dev/ledchar用来读写硬件
子系统 (class)统一组织管理设备/sys/class/led_class/便于分类管理
设备模型 (device model)内核统一抽象bus/device/driver子系统基于它

7. 为什么字符设备要挂子系统?

  • 如果直接裸 cdev:仅 /dev 有节点,sysfs 中无管理
  • 如果挂到子系统
    • /dev 节点
    • /sys/class 路径
    • 更易于热插拔、用户空间管理
    • 可以扩展 attribute 节点(如调节亮度)

所以,规范写法:

字符设备 + 子系统结合,才是完整专业驱动。


8. 小结与今日提炼

✅ 子系统统一管理同类设备,提升 Linux 内核规范性。
✅ 子系统本质上是设备模型的一个应用。
✅ 字符设备可直接使用,也可以挂到子系统,推荐挂载管理。
✅ 电源子系统(regulator)、LED子系统、网卡子系统都是应用范例。


9. 后续学习计划(已升级)

阶段主题备注
✅ 阶段一设备模型 + 字符设备已完成
✅ 阶段二子系统概念与应用今日完成
🔜 阶段三电源子系统(regulator)深度学习明日开始

10. 技术交流

💬 更多 Linux 驱动开发教学,请关注 B 站:【嵌入式Jerry


【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究改进中。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值