struct resource 内核资源描述符
2026/8/25 12:17:20 网站建设 项目流程

struct resource是 Linux 内核中用于描述和统一管理各种系统资源(如I/O端口、内存区域、IRQ号、DMA通道等)的核心数据结构。

它的定义位于include/linux/ioport.h文件中,其结构体定义如下:

struct resource { resource_size_t start; /* 资源的起始地址 */ resource_size_t end; /* 资源的结束地址 */ const char *name; /* 资源的名称 */ unsigned long flags; /* 资源的类型和属性标志 */ struct resource *parent, *sibling, *child; /* 指向资源树中的父、兄弟、子节点 */ };

字段含义详解

字段类型描述
startresource_size_t资源的起始地址(对于I/O端口、内存等地址空间资源)或编号(对于IRQ、DMA等)。
endresource_size_t资源的结束地址。startend共同定义了资源的地址范围。
nameconst char *资源的描述性名称,通常会被导出到用户空间,例如你在/proc/iomem/proc/ioports中看到的名称。
flagsunsigned long用于标识资源的类型(如IORESOURCE_MEM、IORESOURCE_IO)和属性(如IORESOURCE_BUSY、IORESOURCE_READONLY)的位掩码。这是资源管理中最关键的字段之一。
parentstruct resource *指向资源树中该节点的父节点。资源组织成一棵树形结构。
siblingstruct resource *指向同一父节点下的兄弟资源节点的链表指针。
childstruct resource *指向该资源节点的第一个子节点。

资源树结构

内核将所有的同类型资源(如所有I/O内存)组织成一棵资源树。其中,parentsiblingchild这三个字段正是为了构建这棵树:

  • 每个资源都有一个父节点(parent),根节点通常是全局的,如iomem_resource

  • 子节点之间通过sibling指针链接成一个链表。

  • 每个父节点通过child指针指向它的第一个子节点。

这个树形结构有效地管理了资源的层次关系和冲突检测。

flags常用标志说明

flags字段定义了资源的类型和属性,常见的标志位包括:

标志宏定义含义
IORESOURCE_IO0x00000100I/O端口空间。
IORESOURCE_MEM0x00000200内存地址空间。
IORESOURCE_IRQ0x00000400中断号(IRQ)。
IORESOURCE_DMA0x00000800DMA通道。
IORESOURCE_BUSY0x80000000该资源已被驱动程序占用。
IORESOURCE_READONLY0x00004000资源为只读。

code_resourcedata_resourcebss_resource正是通过struct resource来精确描述内核自身各段在物理内存中的地址范围,并通过flags标识类型为IORESOURCE_MEM,然后被添加到全局的iomem_resource资源树中,最终通过/proc/iomem文件呈现给用户。

code_resource.start = __pa_symbol(_text);

code_resource.end = __pa_symbol(_etext)-1;

data_resource.start = __pa_symbol(_etext);

data_resource.end = __pa_symbol(_edata)-1;

bss_resource.start = __pa_symbol(__bss_start);

bss_resource.end = __pa_symbol(__bss_stop)-1;

这段代码的作用是为内核的代码段(.text)、数据段(.data)和BSS段(.bss)分别建立物理地址范围的资源描述符。它通过__pa_symbol宏将内核各段符号的虚拟地址转换为物理地址,并填充到对应的struct resource结构体中。

这段代码位于arch/x86/kernel/setup.csetup_arch函数中,执行时机非常早,是内核初始化自身内存布局的关键一步。

代码解析

  • code_resource:记录内核代码段的物理地址范围。

    • start = __pa_symbol(_text):起始地址是内核代码段的开始。

    • end = __pa_symbol(_etext)-1:结束地址是代码段结束符号的前一个字节。

  • data_resource:记录内核数据段的物理地址范围。

    • start = __pa_symbol(_etext):起始地址紧跟在代码段之后。

    • end = __pa_symbol(_edata)-1:结束地址是数据段结束符号的前一个字节。

  • bss_resource:记录内核BSS段(未初始化全局变量)的物理地址范围。

    • start = __pa_symbol(__bss_start):起始地址是BSS段的开始。

    • end = __pa_symbol(__bss_stop)-1:结束地址是BSS段结束符号的前一个字节。

代码中的-1是因为end字段表示的是最后一个有效字节的地址,而_etext_edata等符号通常指向其段结束位置之后的一个字节。

内核各段布局与链接脚本

这些_text_etext等符号由内核链接脚本vmlinux.lds.S定义,它们共同描绘了内核在内存中的完整布局:

符号含义
_text.text代码段的起始地址。
_etext.text代码段的结束地址(之后是只读数据段)。
_edata.data数据段的结束地址(之后是BSS段)。
__bss_start.bssBSS段的起始地址。
__bss_stop.bssBSS段的结束地址。

核心作用:建立内核资源表

这些struct resource对象(如code_resourcedata_resourcebss_resource)是内核资源管理子系统的一部分。通过将它们注册到资源树中,内核能够:

  1. 提供信息查询接口:用户和系统程序可以通过/proc/iomem文件查看这些段在物理内存中的确切位置和大小。

  2. 防止资源冲突:明确告知内核的内存管理模块,这些物理地址范围已被内核自身占用,不应被其他设备驱动或内存分配器重复分配。

  3. 为内存管理和调试提供支撑:当内核需要映射物理地址或进行内存转储时,这些资源描述符提供了可靠的内核自身定位信息。

因此,这段看似简单的赋值代码,实际上是内核将自己“烙印”到物理内存地图上的一个过程,确保了后续所有内存管理操作的基础是清晰和正确的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询