Linux驱动学习笔记(十)

news2025/6/1 9:55:35
热插拔

1.热插拔:就是带电插拔,即允许用户在不关闭系统,不切断电源的情况下拆卸或安装硬盘,板卡等设备。热插拔是内核和用户空间之间,通过调用用户空间程序实现交互来实现的,当内核发生了某种热拔插事件时,内核就会调用用户空间的程序来实现交互。热插拔机制有devfs、udev和mdev,devfs如今已经不再使用。嵌入式设备上一般使用mdev,X86上一般用udev,当然嵌入式设备上也可以用udev,mdev是udev的简化版本。udev是基于netlink机制实现的,通过udevd守护进程监听内核发送的uevent事件来执行相应的热插拔操作。而mdev是基于uevent helper机制,内核产生的uevent会调用uevent_helper所指的用户程序medv来执行热拔插动作。

2.int kobject_uevent(struct kobject *kobj, enum kobject_action action);函数可用来在内核中向用户空间发送设备事件通知uevent,触发用户态的udev/mdev等设备管理工具响应设备状态变化,该函数执行成功返回0。其中,kobj是关联的内核对象指针,代表触发事件的设备或子系统;action是发生的事件类型,包括下图所示的几种事件:

udevadm是Linux系统中用于管理和调试udev设备管理器的核心命令行工具,它允许用户直接与udev交互,查询设备信息、触发事件、监控设备变动或调试规则。使用方法为:

例如可以使用udevadm monitor命令监听所有内核设备事件,示例如下:

kobject_uevent函数向用户态发送事件时会调用kobject_uevent_env函数,如下图:

kobject_uevent_env函数可用来发送带有环境变量数据的事件。kobject_uevent_env函数会根据事件的类型进行对应的操作,但是这一流程是借助kset来实现的(uevent是通过netlink socket发送给用户空间的应用程序的,而netlink socket是基于kset的),所以发送事件的kobject必须属于某个kset,否则会导致事件发送失败,如下图:

如上图所示,在获取到发送事件的kobject所属的kset以及该kset的事件操作uevent_ops后,kobject_uevent_env函数依次执行这些操作,如下图:

最终kobject_uevent_env函数会广播要发送的事件,以便用户空间的应用程序可以接收并处理这些事件(对应udev)。另外如果定义了CONFIG_UEVENT_HELPER则会调用用户空间的uevent_helper程序(可将其设置成mdev)来处理uevent事件,如下图:

3.kset->uevent_ops中定义了三个函数,如下图:

其中,filter函数用于过滤,即当一个kobject想要向用户空间发送uevent时,由filter函数决定这个uevent是否应该被发送;name函数用于为uevent生成一个特定的名称字符串,这个名称会被添加到uevent的环境变量中,帮助用户空间应用程序识别事件来源;uevent函数来填充或修改发送到用户空间的uevent消息中的环境变量。一个示例如下图:

4.Linux提供了多种方式实现内核和用户空间的数据交换,比如系统调用、sysfs等,但是这些通信机制均为单工通信机制。而netlink是基于socket通信机制,具有双工通信的特点,可以很好的满足内核和用户空间的数据交换。因为netlink是基于socket通信机制,所以需要在用户空间使用socket接口实现。首先介绍几个函数:

  • int socket(int domain, int type, int protocol):用于创建套接字。其中domain表示所用协议,使用netlink机制时将其设置为AF_NETLINK;type表示套接字的类型,指定通信的方式和特性,使用netlink机制时将其设置为SOCK_RAW;protocol表示套接字使用的协议,通常设置为0,让系统自动选择适当的协议,在接收uevent时可将其设置为NETLINK_KOBJECT_UEVENT;该函数调用成功返回创建的套接字对应的文件描述符,失败返回-1并设置errno
  • int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen):用于将创建的套接字与指定的地址结构绑定。其中sockfd为套接字对应的文件描述符;addr为传入参数,在接收uevent时通常使用sockaddr_nl结构体(强转为sockaddr类型),这个结构体成员包括协议族(这里应为AF_NETLINK),当前进程PID;addrlen为addr的长度;该函数绑定成功返回0,失败返回-1并设置errno
  • ssize_t recv(int sockfd, void *buf, size_t len, int flags):用于接收内核发出的uevent事件。注意与一般网络编程不同,在netlink中是不用调用listen函数的,可以直接使用recv函数进行接收。其中sockfd为套接字对应的文件描述符;buf指向接收数据的缓冲区;len指定要读取的数据的字节数;flags指定一些标志用于控制如何接收数据,通常设置为0;成功情况下该函数返回实际读取到的字节数

netlink需要在用户空间循环读取内核发来的uevent,下图是一个例子(可参考讯为Linux驱动视频第十期P5):

5.对于uevent helper机制,要想在kobject_uevent_env函数中调用用户空间的uevent_helper程序来处理uevent事件,则需要定义CONFIG_UEVENT_HELPER,并且需要定义uevent_helper的路径(即CONFIG_UEVENT_HELPER_PATH的值),如下图:

有以下几种配置方法(可参考讯为Linux驱动视频第十期P6):

  • 在编译内核时直接配置CONFIG_UEVENT_HELPER_PATH:make menuconfig打开图形化配置界面后,选中Device Drivers->Generic Driver Options->Support for uevent helper后配置path to uevent helper,即配置uevent_helper的路径(例如可将其设置为/sbin/mdev)
  • make menuconfig打开图形化配置界面后,依次选中:Device Drivers->Generic Driver Options->Support for uevent helper(这一步是打开宏定义CONFIG_UEVENT_HELPER)、File systems->Pseudo fllesystems->/proc file system support、File systems->Pseudo fllesystems-> Sysctl support(/proc/sys)、Networking support。选中上述几个配置之后,就可以通过命令echo /sbin/mdev > /sys/kernel/uevent_helper对uevent_helper进行设置,或通过命令echo /sbin/mdev > /proc/sys/kernel/hotplug对uevent_helper进行设置(这两种设置方法实际就是通过对属性文件进行读写实现的)

一个简单的mdev程序如下图所示(可参考讯为Linux驱动视频第十期P7):

需要注意的是,kobject_uevent_env函数中调用的call_usermodehelper_exec函数是一个在内核空间中调用用户空间程序的函数,该函数执行用户空间程序时,将其作为子进程运行,并将其标准输入、标准输出和标准错误输出重定向到相应的文件描迷符。因此如果在用户空间程序中使用printf打印信息,这些信息将被输出到标准输出文件描述符(文件描述符1),而不是终端。因此需要在调用call_usermodehelper_exec时将标准输出重定向到终端,这样才可以在终端上看到printf输出的信息。

6.实现U盘热插拔的几个步骤,采用udev(可参考讯为Linux驱动视频第十期P8):

  • 首先需要在编译源码时配置所使用的Linux系统支持udev,例如对于buildroot文件系统,执行make menuconfig之后将System configuration->/dev management设置为Dynamic using devtmpfs + eudev表示使用udev
  • 启动系统后在/etc/udev/rules.d/目录下创建一个001.rules文件(若没有rules.d/目录则创建),其中001表示第一个规则文件,.rules是固定后缀。向在001.rules文件写入以下内容:
    KERNEL=="sd[a-z][0-9]",SUBSYSTEM=="block",ACTION=="add",RUN+="/etc/udev/rules.d/usb/usb-add.sh %k"
    SUBSYSTEM=="block",ACTION=="remove",RUN+="/etc/udev/rules.d/usb/usb-remove.sh"
    第一行表示当新增一个usb设备,执行/etc/udev/rules.d/usb/usb-add.sh脚本文件,并传入参数sd[a-z][0-9],第二行表示当移除一个usb设备,执行/etc/udev/rules.d/usb/usb-remove.sh脚本文件
  • 分别创建/etc/udev/rules.d/usb/usb-add.sh和/etc/udev/rules.d/usb/usb-remove.sh文件,分别写入以下内容:
    #!/bin/sh
    
    /bin/mount -t vfat /dev/$1 /mnt
    sync
    #!/bin/sh
    
    sync
    /bin/unmount -l /mnt

还可以在/lib/udev/rules.d/目录下创建规则文件,但是/etc/udev/rules.d/比/lib/udev/rules.d的优先级高。TF卡的udev热插拔实现方式和U盘类似,只是U盘的节点名格式为sd[a-z][0-9],而TF卡的节点名格式为mmcblk[0-9]p[0-9]。采用mdev实现U盘和TF卡的热插拔步骤与udev类似,可参考讯为Linux驱动视频第十期P10、P11。

7.USBmount是一个用于自动挂载USB存储设备的工具,它可以在Linux系统中自动挂载插入的USB存储设备并在设备拔出时自动卸载。USBmount的工作原理是通过udev监视USB设备的插拔事件,并在检测到设备插入时自动挂载设备,检测到设备拔出时自动卸载设备。USBmount不需要手动挂载或卸载USB存储设备,因此可以方便地在嵌入式系统中使用(USBmount使用方式可参考讯为Linux驱动视频第十期P12)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2392474.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TI dsp FSI (快速串行接口)

简介 快速串行接口(FSI - Fast Serial Interface )模块是一种串行通信外设,能够在隔离设备之间实现可靠的高速通信。在两个没有共同电源和接地连接的电子电路必须交换信息的情况下,电气隔离设备被使用。 虽然隔离设备促进了信号通…

责任链模式:构建灵活可扩展的请求处理体系(Java 实现详解)

一、责任链模式核心概念解析 (一)模式定义与本质 责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,其核心思想是将多个处理者对象连成一条链,并沿着这条链传递请求,直到有某…

wechat-003-学习笔记

1.路由跳转页面:携带的参数会出现在onlaod中的options中。 注意:原生小程序对路由传参的长度也有限制,过长会被截掉。 2.wx.setNavigationBarTitle(Object object) 动态设置当前页面的标题 3.在根目录中的app.json文件中配置 后台播放音乐的能…

【大模型微调】魔搭社区GPU进行LLaMA-Factory微调大模型自我认知

文章概要: 本文是一篇详细的技术教程,介绍如何使用魔搭社区(ModelScope)的GPU资源来进行LLaMA-Factory的模型微调。文章分为11个主要步骤,从环境准备到最终的模型测试,系统地介绍了整个微调流程。主要内容包…

【数据结构】哈希表的实现

文章目录 1. 哈希的介绍1.1 直接定址法1.2 哈希冲突1.3 负载因子1.4 哈希函数1.4.1 除法散列法/除留余数法1.4.2 乘法散列法1.4.3 全域散列法 1.5 处理哈希冲突1.5.1 开放地址法1.5.1.1 线性探测1.5.1.2 二次探测1.5.1.3 双重探测1.5.1.4 三种探测方法对比 1.6.3 链地址法 2. 哈…

永磁同步电机控制算法--基于电磁转矩反馈补偿的新型IP调节器

一、基本原理 先给出IP速度控制器还是PI速度控制器的传递函数: PI调节器 IP调节器 从IP速度控制器还是PI速度控制器的传递函数可以看出,系统的抗负载转矩扰动能力相同,因此虽然采用IP速度控制器改善了转速环的超调问题,但仍然需要通过其他途…

RabbitMQ 应用 - SpringBoot

以下介绍的是基于 SpringBoot 的 RabbitMQ 开发介绍 Spring Spring AMQP RabbitMQ RabbitMQ tutorial - "Hello World!" | RabbitMQ 工程搭建步骤: 1.引入依赖 2.编写 yml 配置,配置基本信息 3.编写生产者代码 4.编写消费者代码 定义监听类,使用 RabbitListener…

基于递归思想的系统架构图自动化生成实践

文章目录 一、核心思想解析二、关键技术实现1. 动态布局算法2. 样式规范集成3. MCP服务封装三、典型应用场景四、最佳实践建议五、扩展方向一、核心思想解析 本系统通过递归算法实现了Markdown层级结构到PPTX架构图的自动转换,其核心设计思想包含两个维度: 数据结构递归:将…

OpenGL Chan视频学习-9 Index Buffers inOpenGL

bilibili视频链接: 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函数网站: docs.gl 说明: 1.之后就不再单独整理网站具体函数了,网站直接翻译会…

Nginx安全防护与HTTPS部署实战

目录 前言一. 核心安全配置1. 隐藏版本号2. 限制危险请求方法3. 请求限制(CC攻击防御)(1)使用nginx的limit_req模块限制请求速率(2)压力测试验证 4. 防盗链 二. 高级防护1. 动态黑名单(1&#x…

JAVA重症监护系统源码 ICU重症监护系统源码 智慧医院重症监护系统源码

智慧医院重症监护系统源码 ICU重症监护系统源码 开发语言:JavaVUE ICU护理记录:实现病人数据的自动采集,实时记录监护过程数据。支持主流厂家的监护仪、呼吸机等床旁数字化设备的数据采集。对接检验检查系统,实现自动化录入。喜…

python:机器学习(KNN算法)

本文目录: 一、K-近邻算法思想二、KNN的应用方式( 一)分类流程(二)回归流程 三、API介绍(一)分类预测操作(二)回归预测操作 四、距离度量方法(一)…

【笔记】2025 年 Windows 系统下 abu 量化交易库部署与适配指南

#工作记录 前言 在量化交易的学习探索中,偶然接触到 2017 年开源的 abu 量化交易库,其代码结构和思路对新手理解量化回测、指标分析等基础逻辑有一定参考价值。然而,当尝试在 2025 年的开发环境中部署这个久未更新的项目时,遇到…

小程序 - 视图与逻辑

个人简介 👨‍💻‍个人主页: 魔术师 📖学习方向: 主攻前端方向,正逐渐往全栈发展 🚴个人状态: 研发工程师,现效力于政务服务网事业 🇨🇳人生格言: “心有多大,舞台就有多大。” 📚推荐学习: 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒T…

ChatGPT Plus/Pro 订阅教程(支持支付宝)

订阅 ChatGPT Plus GPT-4 最简单,成功率最高的方案 1. 登录 chat.openai.com 依次点击 Login ,输入邮箱和密码 2. 点击升级 Upgrade 登录自己的 OpenAI 帐户后,点击左下角的 Upgrade to Plus,在弹窗中选择 Upgrade plan。 如果…

[蓝帽杯 2022 初赛]网站取证_2

一、找到与数据库有关系的PHP文件 打开内容如下,发现数据库密码是函数my_encrypt()返回的结果。 二、在文件夹encrypt中找到encrypt.php,内容如下,其中mcrypt已不再使用,所以使用php>7版本可能没有执行结果,需要换成较低版本…

安装 Node.js 和配置 cnpm 镜像源

一、安装 Node.js 方式一:官网下载(适合所有系统) 访问 Node.js 官网 推荐选择 LTS(长期支持)版本,点击下载安装包。 根据系统提示一步步完成安装。 方式二:通过包管理器安装(建…

MacOS内存管理-删除冗余系统数据System Data

文章目录 一、问题复现二、解决思路三、解决流程四、附录 一、问题复现 以题主的的 Mac 为例,我们可以看到System Data所占数据高达77.08GB,远远超出系统所占内存 二、解决思路 占据大量空间的是分散在系统中各个位置Cache数据; 其中容量最…

行为型:中介者模式

目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 5、注意事项 1、核心思想 目的:通过引入一个中介对象来封装一组对象之间的交互,解决对象间过度耦合、频繁交互的问题。不管是对象引用维护还是消息的转发&am…

光谱相机在生态修复监测中的应用

光谱相机通过多维光谱数据采集与智能分析技术,在生态修复监测中构建起‌“感知-评估-验证”‌的全周期管理体系,其核心应用方向如下: 一、土壤修复效能量化评估 ‌重金属污染动态监测‌ 通过短波红外(1000-2500nm)波…