news 2026/7/2 4:08:33

struct resource

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
struct resource

struct resource是 Linux 内核中用于描述硬件设备「物理资源」的核心数据结构,核心作用是记录设备的物理地址、中断号、DMA 通道等硬件资源信息,同时提供资源申请、释放、冲突检测的机制,避免多个驱动抢占同一硬件资源。

无论是传统的平台驱动,还是基于设备树的驱动,最终都会将硬件资源解析为struct resource,它是驱动访问硬件资源的「入口凭证」。

核心定位

struct resource的核心作用有两个:

  1. 资源描述:将硬件设备的「物理资源」(IO 内存、中断、DMA、IO 端口等)封装为统一的数据结构,方便内核和驱动管理;
  2. 资源管理:内核通过该结构体实现资源的「申请(占用)、释放、冲突检测」,确保同一硬件资源不会被多个驱动同时使用(比如两个驱动同时申请同一个中断号)。

简单来说:

  • 硬件设备有「物理地址 0x12340000」「中断号 10」这类资源;
  • 内核 / 设备树将这些资源封装为struct resource数组;
  • 驱动通过专门的 API 申请这些资源,申请成功后才能访问对应的硬件,释放时归还资源。

它的定义在include/linux/ioport.h头文件中,是所有驱动开发(字符、块、网络设备)的必备知识点。

完整定义(Linux 5.x 及以上版本)

struct resource { resource_size_t start; // 资源的起始地址/编号(物理地址、中断号等) resource_size_t end; // 资源的结束地址/编号(物理地址、中断号等) const char *name; // 资源名称(用于标识资源,方便调试) unsigned long flags; // 核心:资源类型标志(区分IO内存、中断、DMA等) struct resource *parent; // 父资源指针(用于构建资源层级关系) struct resource *sibling; // 兄弟资源指针(用于构建资源链表) struct resource *child; // 子资源指针(用于构建资源树) };

关键字段深度解析

start&end:资源的「范围标识」

这两个字段共同描述资源的有效范围,具体含义由flags(资源类型)决定:

  • 当资源是「IO 内存」(IORESOURCE_MEM
    • start:物理内存的起始地址(如设备寄存器的基地址0x12340000);
    • end:物理内存的结束地址(如0x12340fff,表示资源长度为0x1000字节);
    • 资源长度 =end - start + 1
  • 当资源是「中断」(IORESOURCE_IRQ
    • 对于单个中断号:start = end = 中断号(如start=10end=10);
    • 对于中断号范围(极少用):start是起始中断号,end是结束中断号。
  • 当资源是「IO 端口」(IORESOURCE_IO,x86 架构常用)
    • start:IO 端口的起始编号;
    • end:IO 端口的结束编号。
  • 当资源是「DMA 通道」(IORESOURCE_DMA
    • start=end= DMA 通道编号。

示例:描述一个 UART 设备的 IO 内存资源(基地址 0x12340000,长度 0x1000)

struct resource uart_mem_res = { .start = 0x12340000, .end = 0x12340000 + 0xfff, // 结束地址 = 基地址 + 长度 - 1 .name = "uart_mem", .flags = IORESOURCE_MEM, };

flags:核心字段,资源「类型标识」

flags是无符号长整型,用于标识资源的类型、属性、访问权限,核心是「资源类型宏」,其他属性宏作为补充。

① 核心资源类型宏(最常用)

宏定义资源类型适用场景
IORESOURCE_MEMIO 内存(物理内存映射)设备寄存器、片上外设内存(ARM/ARM64 最常用)
IORESOURCE_IRQ中断资源设备的中断号(如 SPI、UART、网卡中断)
IORESOURCE_IOIO 端口x86 架构的传统 IO 端口(如 0x3f8 对应串口 1)
IORESOURCE_DMADMA 通道设备的 DMA 传输通道(如磁盘、网卡 DMA)
IORESOURCE_BUS总线资源设备所属的总线地址范围

② 补充属性宏(辅助描述资源特性)

宏定义核心含义
IORESOURCE_EXCLUSIVE资源独占使用(不允许共享)
IORESOURCE_SHAREABLE资源可共享(如多个设备共享同一中断)
IORESOURCE_PREFETCH资源支持预取(如内存缓存)
IORESOURCE_READONLY资源只读(不可写入,如某些状态寄存器)

示例:描述一个可共享的中断资源(中断号 10,电平触发)

struct resource uart_irq_res = { .start = 10, .end = 10, .name = "uart_irq", .flags = IORESOURCE_IRQ | IORESOURCE_SHAREABLE, // 中断资源 + 可共享 };

name:资源名称,用于「调试与标识」

  • 可选字段,用于给资源命名,方便调试时识别资源类型;
  • 内核日志、/sys文件系统中会显示该名称,帮助排查资源冲突问题;
  • 示例:"uart_mem""eth0_irq""sdma_channel_0"

parent/sibling/child:资源「层级管理」

  • 用于构建资源的「树状 / 链表结构」,方便内核管理一组相关资源(如一个设备的多个 IO 内存、多个中断);
  • 驱动开发者通常无需手动操作这些字段,由内核自动维护;
  • 示例:一个网卡设备有「IO 内存」「中断」「DMA 通道」三个资源,内核会将它们组织为兄弟链表,挂在设备的资源根节点下。

struct resource支持的核心资源类型

日常驱动开发中,最常用的是IORESOURCE_MEM(IO 内存)IORESOURCE_IRQ(中断),两者覆盖了 90% 以上的嵌入式驱动场景,下面展开详解。

IORESOURCE_MEM(IO 内存)

核心场景

ARM/ARM64 架构下的片上外设(UART、GPIO、SPI)、PCIe 设备(网卡、NVMe)的寄存器访问,都是通过 IO 内存实现的。

驱动中使用流程
  1. 获取资源:通过platform_get_resource()从设备中获取 IO 内存资源;
  2. 申请资源:通过devm_request_mem_region()申请占用该内存区域(避免冲突);
  3. 内存映射:通过devm_ioremap_resource()将物理地址映射为内核虚拟地址(内核无法直接访问物理地址);
  4. 访问硬件:通过readl()/writel()读写映射后的虚拟地址(操作设备寄存器);
  5. 释放资源:驱动卸载时,devm_系列函数会自动释放映射和资源(无需手动操作)。

IORESOURCE_IRQ(中断)

核心场景

设备的异步事件通知(如网卡收包、UART 数据到达、磁盘 IO 完成),都需要通过中断实现。

驱动中使用流程
  1. 获取资源:通过platform_get_irq()从设备中获取中断号(封装自platform_get_resource());
  2. 申请中断:通过devm_request_irq()申请中断,注册中断处理函数;
  3. 处理中断:中断触发时,执行注册的中断处理函数(顶半部);
  4. 释放中断:驱动卸载时,devm_系列函数自动释放中断(无需手动操作)。

设备树与struct resource的关联

在基于设备树的驱动开发中,我们并不会手动定义struct resource,而是由内核自动将设备树节点中的硬件资源解析为struct resource数组,驱动只需通过 API 获取即可,这也是设备树的核心优势之一。

1. 设备树节点 →struct resource映射关系

设备树中的核心资源属性,会被内核自动解析为对应的struct resource

设备树属性对应struct resource类型映射逻辑
regIORESOURCE_MEM/IORESOURCE_IOreg中的<addr size>解析为start=addrend=addr+size-1
interruptsIORESOURCE_IRQinterrupts中的中断号解析为start=end=irq
dmaIORESOURCE_DMAdma中的通道号解析为start=end=dma_channel

2. 示例:设备树节点与内核解析结果

(1)设备树节点定义
uart1: serial@12340000 { compatible = "fsl,imx6ul-uart"; reg = <0x12340000 0x1000>; // 物理地址 0x12340000,长度 0x1000 interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; // 中断号 10 };
(2)内核自动解析后的struct resource数组

内核会为该设备创建一个resource数组,包含两个元素:

// 第 0 个资源:IO 内存 struct resource res[0] = { .start = 0x12340000, .end = 0x12340fff, .name = "serial@12340000", .flags = IORESOURCE_MEM, }; // 第 1 个资源:中断 struct resource res[1] = { .start = 10, .end = 10, .name = "serial@12340000", .flags = IORESOURCE_IRQ, };
(3)驱动中获取解析后的资源

驱动中通过platform_get_resource()/platform_get_irq()即可获取上述资源,无需手动定义,实现了硬件信息与驱动代码的解耦。

关键注意事项与最佳实践

  1. 优先使用devm_系列 API:申请资源 / 映射内存时,优先使用devm_request_mem_region()devm_ioremap_resource()devm_request_irq()devm_前缀函数,这些函数会自动管理资源生命周期,驱动卸载时无需手动释放,避免资源泄漏。
  2. 资源申请失败必须处理platform_get_resource()devm_ioremap_resource()等函数返回NULL或错误码时,必须打印错误日志并返回,不能继续执行后续硬件操作,否则会导致系统崩溃。
  3. 内核无法直接访问物理地址struct resource中记录的start/end是物理地址,内核态代码无法直接访问,必须通过ioremap()系列函数映射为虚拟地址后,才能用readl()/writel()读写。
  4. 中断资源的start=end:单个中断号的资源,startend必须相等,内核才会识别为有效中断资源。
  5. 资源冲突排查:如果驱动申请资源失败,可通过/proc/iomem(查看 IO 内存占用)和/proc/interrupts(查看中断占用)排查是否有其他驱动抢占了该资源。

关键要点

  1. struct resource是 Linux 内核描述硬件物理资源的统一数据结构,核心字段是start/end(资源范围)和flags(资源类型)。
  2. 最常用的资源类型是IORESOURCE_MEM(IO 内存)和IORESOURCE_IRQ(中断),覆盖绝大多数嵌入式驱动场景。
  3. 基于设备树的驱动中,内核会自动将设备树节点的reg/interrupts等属性解析为struct resource,驱动只需通过标准 API 获取即可。
  4. 最佳实践是优先使用devm_系列函数管理资源,避免资源泄漏,同时必须处理资源申请失败的场景。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 9:15:55

百考通AI开题指南:本科论文第一步的高效通关方案

随着毕业季的临近&#xff0c;又一届本科生站在了学术生涯的重要关口——毕业论文。作为整个研究过程的蓝图&#xff0c;开题报告的质量直接决定了后续工作的方向与深度。然而&#xff0c;面对选题论证、框架构建、格式规范等多重挑战&#xff0c;不少同学陷入了“不知从何下手…

作者头像 李华
网站建设 2026/6/29 0:06:17

百考通:汇聚前沿技术资源,赋能开发者高效成长

在数字化浪潮席卷全球的今天&#xff0c;技术开发与项目实践已成为推动创新的核心引擎。对于广大开发者、学生及企业技术团队而言&#xff0c;优质的技术资源与高效的学习工具是突破瓶颈、加速成长的关键。百考通&#xff08;https://www.baikaotongai.com&#xff09;应运而生…

作者头像 李华
网站建设 2026/6/28 22:59:29

百考通AI开题报告生成:让学术研究,从“精准规划“开始

在学术研究的起点——开题报告撰写中&#xff0c;无数学生与研究者常常面临格式混乱、逻辑不清、内容空洞等困境。从确定研究方向到梳理技术路线&#xff0c;从撰写创新点到规范参考文献&#xff0c;传统开题报告的撰写不仅耗时耗力&#xff0c;更可能因专业表达不足而影响研究…

作者头像 李华
网站建设 2026/7/2 3:54:30

Vue 响应式数据失效全解析:从原理机制到工程实践

Vue 响应式数据失效全解析&#xff1a;从原理机制到工程实践 Vue 的响应式系统是其核心竞争力之一&#xff0c;让数据变更自动触发视图更新。但在实际开发中&#xff0c;常常遇到“响应式失效”的问题&#xff1a;数据变了&#xff0c;但视图没更新。这篇文章从Vue 响应式原理…

作者头像 李华
网站建设 2026/7/2 1:43:38

C :结构体详解

C语言结构体&#xff08;struct&#xff09;超级详解 从最基础到最容易被面试官问到的进阶用法&#xff0c;一次性讲透&#xff01; 1. 结构体最基础的概念 struct 结构体标签名 {类型1 成员名1;类型2 成员名2;...类型N 成员名N; };最常用的三种写法&#xff08;请牢牢记住…

作者头像 李华
网站建设 2026/7/1 21:24:14

‌边缘推理测试:TinyML模型在IoT设备的长期稳定性验证框架‌

边缘智能时代的测试新挑战 随着TinyML技术加速渗透工业物联网&#xff08;IIoT&#xff09;场景&#xff0c;模型在资源受限设备&#xff08;如ESP32&#xff09;的长期运行稳定性成为质量保障核心痛点。传统测试方法难以覆盖数月级持续推理中的内存泄漏、精度漂移等隐患&…

作者头像 李华