【嵌入式linux学习】01_1应用层open怎么到硬件控制
【嵌入式linux学习】从应用层的open到led闪烁这个blog讲讲为什么我在应用层写一句简单的open(/dev/led, O_RDWR)电路板上的 LED 灯就能亮起来整个过程可以看作是一次跨越三个“世界”的通信用户空间 (User Space)APP 只认识文件路径字符串如/dev/led。内核空间 (Kernel Space)内核只认识数据结构inode,cdev,file。硬件世界 (Hardware)硬件只认识物理电信号高低电平。我们的目标就是要把“字符串”变成“电信号”。总结一下1️⃣通过open产生系统调用到达内核层_通过路径查找Path Walk机制逐层解析目录,找到相应结构体inode——识别到是一个字符设备——内核根据inode-i_rdev(设备号)在内核的cdev_map散列表中查找对应的struct cdev对象 ——当chrdev_open找到cdev后它做了一个赋值操作filp-f_op cdev-ops;这里的cdev-ops就是你写的my_fops在这一行代码执行之前这个文件只是一个普通的、冷冰冰的设备节点内核只知道它有个设备号。在这一行代码执行之后这个struct file就“活”了。它绑定到了你的驱动上。关键点不仅是open用户层对这个文件描述符 (fd) 调用的read、write、ioctl全都会绕过通用逻辑直接跳转到你写的my_read、my_write函数里去。2️⃣找到设备后通过物理地址和虚拟地址映射控制寄存器从而对LED进行控制文章目录【嵌入式linux学习】从应用层的open到led闪烁第一阶段 (VFS 层)第一步从字符串到 Inode (VFS 的工作)第二步识别“我是个字符设备”第三步默认处理函数 chrdev_open第四步偷天换日 (最关键的一步)具体代码第二阶段驱动层1. 次设备号 (Minor Number) 的作用2. 代码实现逻辑第三阶段硬件层1. 物理地址与虚拟地址2. 寄存器操作总结第一阶段 (VFS 层)当 APP 调用open时系统调用触发中断CPU 陷入内核态执行sys_open。内核的第一件事是根据路径找到“负责这件事的人”。第一步从字符串到 Inode (VFS 的工作)APP 传入的是一个字符串路径如/dev/hello。内核中的sys_open无法直接操作字符串它必须把这个路径解析成内核能理解的对象。内核通过路径查找Path Walk机制逐层解析目录。最终找到/dev/hello对应的目录项结构体dentry。每个dentry都指向一个inode(索引节点)。关键点inode是文件或设备节点在文件系统中的静态表示。无论被打开多少次inode只有一个。它里面存储了最关键的信息设备号Major/Minor。第二步识别“我是个字符设备”找到inode后内核检查inode-i_mode。如果是普通文件按文件系统逻辑处理。如果是字符设备文件 (S_IFCHR)内核会意识到“这不是普通文件我需要找到对应的驱动。”此时inode结构体中的i_rdev字段包含主/次设备号成为了连接驱动的钥匙。第三步默认处理函数chrdev_open在inode被初始化时通常是mknod或device_create时字符设备的i_fop默认被指向了一个通用的内核函数def_chr_fops。当 VFS 尝试打开这个文件时它首先调用的是这个默认的def_chr_fops-open也就是chrdev_open。第四步偷天换日 (最关键的一步)在chrdev_open函数内部发生了一次“移花接木”内核根据inode-i_rdev(设备号)在内核的cdev_map散列表中查找对应的struct cdev对象。找到cdev后内核将cdev中保存的file_operations也就是你写的驱动代码my_fops拿出来。替换将当前文件对象 (struct file) 的f_op指针修改为你写的驱动fops。调用最后手动调用你写的.open函数并将inode和file传给你。具体代码// 伪代码内核层处理 open 系统调用的简化逻辑intsys_open(constchar*filename,intflags){// 1. 路径解析通过 filename 找到 inodestructinode*inodepath_lookup(filename);// 2. 创建 file 结构体代表本次会话structfile*filpalloc_file();filp-f_opinode-i_fop;// 此时还是默认的 def_chr_fops// 3. 调用 open// 如果是字符设备这里调用的是 chrdev_openif(filp-f_op-open){returnfilp-f_op-open(inode,filp);}}// 字符设备通用的 open 函数intchrdev_open(structinode*inode,structfile*filp){// 1. 根据 inode-i_rdev (设备号) 找到 cdevstructcdev*pinode-i_cdev;if(!p){kobjkobj_lookup(cdev_map,inode-i_rdev,...);pcontainer_of(kobj,structcdev,kobj);}// 2. 关键将 file 的操作集替换为驱动定义的 fopsfilp-f_opfops_get(p-ops);// 3. 真正调用你自己写的驱动 open 函数if(filp-f_op-open){returnfilp-f_op-open(inode,filp);}}第二阶段驱动层现在执行流终于进入了你写的驱动代码中的.open函数。intmy_driver_open(structinode*inode,structfile*file);这个时候最关键的问题来了驱动怎么知道你要打开具体的哪一个硬件假设你的驱动管理了 4 个 LED 灯APP 打开/dev/led0驱动怎么保证不去操作 LED11. 次设备号 (Minor Number) 的作用答案就在inode参数里。主设备号决定了用哪个驱动程序找对类。次设备号决定了用该驱动下的哪个具体设备找对人。2. 代码实现逻辑在驱动的open函数中通常有以下标准操作structmy_led_dev{void__iomem*reg_base;// 寄存器基地址intgpio_pin;// 具体引脚号};// 假设我们有多个 LED 设备对象structmy_led_devled_devs[4];intmy_driver_open(structinode*inode,structfile*file){// 1. 获取次设备号intminoriminor(inode);// 2. 根据次设备号找到对应的硬件描述结构体structmy_led_dev*devled_devs[minor];// 3. 【最佳实践】将私有数据挂在 file 结构体上// 这样以后 read/write 函数直接从 file-private_data 取不用再看 inodefile-private_datadev;return0;// 成功}第三阶段硬件层找到了代表 LED0 的结构体led_devs[0]最后一步就是让硬件动起来。1. 物理地址与虚拟地址CPU 不能直接访问物理地址如0x10008000Linux 内核运行在虚拟地址空间。 在驱动初始化阶段module_init或probe我们必须做一次映射// 将物理地址映射为内核可操作的虚拟地址dev-reg_baseioremap(PHYS_ADDR_LED_CTRL,SIZE);2. 寄存器操作回到open函数当我们拿到了dev结构体其实就拿到了那个映射好的reg_base指针。 虽然open通常只做初始化如上电但为了演示假设我们在 open 时点亮它// 读-改-写 操作u32 valioread32(dev-reg_base);// 读取硬件寄存器当前状态val|(1dev-gpio_pin);// 修改位iowrite32(val,dev-reg_base);// 写回硬件当iowrite32执行的那一瞬间CPU 通过总线向物理内存地址发送了电信号硬件控制器接收到信号驱动了 MOS 管电流导通LED 灯亮了总结用户态调用open(/dev/xxx)后触发系统调用内核通过路径查找定位到对应的 inode 发现是字符设备后根据inode-i_rdev在cdev_map中找到对应的struct cdev 并将其中的file_operations绑定到当前文件对象 随后执行驱动实现的open函数。实际的硬件操作通常在驱动的probe阶段完成寄存器映射并在read/write/ioctl等文件操作中通过访问寄存器来控制硬件如果把这个过程比作一次“寄快递”APP (open)你在快递单上填了一个地址/dev/led0路径。VFS (内核)快递公司根据地址查库发现这是寄给“老王公司”驱动程序下的“0号员工”次设备号的。Driver (驱动)老王公司收到件派单给 0 号员工。0 号员工查阅手册按下了他办公桌上的开关ioremap 后的虚拟地址。Hardware (硬件)开关连接的电缆通电终点的灯亮起。

相关新闻

DS24B33

DS24B33

DS24B33特性4096位非易失EEPROM划分为16个256位存储页读、写操作向下兼容于DS2433256位暂存器采用严格的读/写协议操作,保证数据传输完整性唯一的、由工厂编程的64位注册码保证器件选择无误,确保每个器件绝对识别切换点滞回可以在嘈杂环境下获得最佳性能…

2026/6/23 16:20:00阅读更多 →
3分钟构建你的离线语音识别系统:Whisper.cpp终极指南

3分钟构建你的离线语音识别系统:Whisper.cpp终极指南

3分钟构建你的离线语音识别系统:Whisper.cpp终极指南 【免费下载链接】whisper.cpp Port of OpenAIs Whisper model in C/C 项目地址: https://gitcode.com/GitHub_Trending/wh/whisper.cpp 在AI技术飞速发展的今天,你是否还在为云端语音识别的隐…

2026/6/23 16:20:00阅读更多 →
C语言学习笔记20260519—如何判断输入的自然数是否为素数

C语言学习笔记20260519—如何判断输入的自然数是否为素数

如何判断输入的自然数是否为素数 1. 素数知识点 1)素数是大于 1,除了 1 和它自己,别的数都除不尽它的自然数 。 2)素数:只能被 1 和自己整除(因子数 2) 3)非素数:因子数…

2026/6/23 16:14:59阅读更多 →
【普中51单片机按下矩阵右下角按键,小灯每0.5s从左往右依次闪烁,5s后全部熄灭】2024-7-13

【普中51单片机按下矩阵右下角按键,小灯每0.5s从左往右依次闪烁,5s后全部熄灭】2024-7-13

缘由普中51单片机按下矩阵右下角按键,小灯每0.5s从左往右依次闪烁,5s后全部熄灭,_嵌入式-CSDN问答 #include "reg52.h" unsigned char Js0;//中断计时 bit k0; unsigned char JianPanShaoMiao(/*使用行列反转扫描法*/) { unsig…

2026/6/23 17:20:12阅读更多 →
通俗易懂理解RANSAC算法

通俗易懂理解RANSAC算法

RANSAC(Random Sample Consensus),翻译为随机抽样一致算法。 算法思路:从所有观测中随机找到几个尽可能少的点去拟合模型,拟合后依次计算模型和所有观测数据的残差,当残差小于给定的阈值时,就将其判断为内点,大于给定的阈值时,就判断为外点,并统计内点的数量,然后再次…

2026/6/23 17:20:12阅读更多 →
QtBitcoinTrader安全机制详解:AES-256加密与RSA保护如何保障你的资产安全 [特殊字符]

QtBitcoinTrader安全机制详解:AES-256加密与RSA保护如何保障你的资产安全 [特殊字符]

QtBitcoinTrader安全机制详解:AES-256加密与RSA保护如何保障你的资产安全 🔒 【免费下载链接】QtBitcoinTrader Secure multi crypto exchange trading client 项目地址: https://gitcode.com/gh_mirrors/qt/QtBitcoinTrader QtBitcoinTrader是一…

2026/6/23 17:20:12阅读更多 →
CrossRef API资源组件全解析:works、funders与members的终极指南

CrossRef API资源组件全解析:works、funders与members的终极指南

CrossRef API资源组件全解析:works、funders与members的终极指南 【免费下载链接】rest-api-doc Documentation for Crossrefs REST API. For questions or suggestions, see https://community.crossref.org/ 项目地址: https://gitcode.com/gh_mirrors/re/rest-…

2026/6/23 17:20:12阅读更多 →
Coblocks入门教程:零基础打造响应式WordPress网站的7个步骤

Coblocks入门教程:零基础打造响应式WordPress网站的7个步骤

Coblocks入门教程:零基础打造响应式WordPress网站的7个步骤 【免费下载链接】coblocks A suite of professional page building content blocks for the WordPress Gutenberg block editor. 项目地址: https://gitcode.com/gh_mirrors/co/coblocks Coblocks…

2026/6/23 17:20:12阅读更多 →
为什么这个DevOps工具集合能入选GitHub Trending?awesome-devops背后的完整故事

为什么这个DevOps工具集合能入选GitHub Trending?awesome-devops背后的完整故事

为什么这个DevOps工具集合能入选GitHub Trending?awesome-devops背后的完整故事 【免费下载链接】awesome-devops This is my awesome list with all open source and free applications that you can use in your management 项目地址: https://gitcode.com/gh_m…

2026/6/23 17:15:12阅读更多 →
【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体 一文搞定到底什么是智能体【人工智能】一文搞定到底什么是智能体一. LM,WorkFlow,Agent分别有什么么不同二. Agent的思考过程是怎样的三. Agent的五个核心部分1)LLM2)Prompt3)Me…

2026/6/23 7:04:52阅读更多 →
嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

1. 嵌入式GUI控件:从原理到实战的深度解析在嵌入式系统开发中,图形用户界面(GUI)的设计与实现往往是项目从“能用”到“好用”的关键一跃。不同于资源充沛的PC或移动平台,嵌入式设备的GUI需要在有限的CPU性能、内存空间…

2026/6/23 1:55:32阅读更多 →
Google AI Studio 300美元额度的真相与实战指南

Google AI Studio 300美元额度的真相与实战指南

1. 这300美金不是“送钱”,而是Google埋下的第一道技术门槛 你看到标题里那个醒目的“$300美金”时,第一反应可能是:又一个免费额度?领完就完事?我亲手试过——这300美金根本不是红包,而是一张入场券&…

2026/6/23 5:55:37阅读更多 →
2026年京东云 618 活动 Hermes Agent/OpenClaw配置Token Plan新手必看指南

2026年京东云 618 活动 Hermes Agent/OpenClaw配置Token Plan新手必看指南

2026年京东云 618 活动 Hermes Agent/OpenClaw配置Token Plan新手必看指南。OpenClaw是开源的个人AI助手,Hermes Agent则是一个能自我进化的AI智能体框架。阿里云提供计算巢、轻量服务器及无影云电脑三种部署OpenClaw 与 Hermes Agent的方案、百炼Token Plan兼容主流…

2026/6/23 0:00:38阅读更多 →
2026年北京电子沙盘制作公司深度评测:从技术选型到落地效果,谁在真正定义“数字+实体”的融合边界?

2026年北京电子沙盘制作公司深度评测:从技术选型到落地效果,谁在真正定义“数字+实体”的融合边界?

模块一:行业背景——百亿赛道爆发,北京市场的特殊性与选型困局2026年,电子沙盘行业已走过“要不要做”的讨论,进入“找谁做、怎么做”的深水区。据行业研究机构数据,2025年国内电子沙盘市场规模已突破85亿元&#xff0…

2026/6/23 0:00:38阅读更多 →
音视频场景下的 Java 开发者面试:技术与挑战

音视频场景下的 Java 开发者面试:技术与挑战

面试互联网大厂:从音视频场景看 Java 开发者的技能与挑战 在互联网大厂求职的面试中,Java 开发者往往需要面对严苛的技术问题。今天,我们将通过一位名叫燕双非的搞笑程序员与严肃的面试官之间的对话,看看在音视频场景下&#xff0…

2026/6/23 0:00:38阅读更多 →