Linux内核态获取System RAM范围的接口或方法

在Linux内核态中,获取System RAM范围的常用方法如下:

方法一:遍历资源树(iomem_resource)

通过遍历内核资源树iomem_resource,查找类型为IORESOURCE_SYSTEM_RAM的资源节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <linux/ioport.h>

void print_system_ram_ranges(void) {
struct resource *res;

read_lock(&resource_lock);
for (res = iomem_resource.child; res != NULL; res = res->sibling) {
if ((res->flags & IORESOURCE_TYPE_BITS) == IORESOURCE_SYSTEM_RAM) {
printk("System RAM: %pap - %pap\n", &res->start, &res->end);
}
}
read_unlock(&resource_lock);
}

注意事项

  • 需持有resource_lock读锁确保线程安全。
  • 使用%pap格式符打印resource结构的地址(需支持该格式的内核版本)。

方法二:使用walk_iomem_res_desc函数

内核提供walk_iomem_res_desc函数遍历特定类型的资源:

1
2
3
4
5
6
7
8
9
10
#include <linux/ioport.h>

static int system_ram_cb(struct resource *res, void *arg) {
printk("System RAM: %pap - %pap\n", &res->start, &res->end);
return 0;
}

void print_system_ram_ranges(void) {
walk_iomem_res_desc(IORES_DESC_NONE, IORESOURCE_SYSTEM_RAM, 0, ULONG_MAX, NULL, system_ram_cb);
}

说明

  • 该函数自动处理锁和资源遍历,更为简洁安全。
  • walk_iomem_res_desc的参数指定资源类型和回调函数。

方法三:使用memblock(早期内核)

在支持memblock且未释放的配置中,遍历memblock.memory

1
2
3
4
5
6
7
8
9
#include <linux/memblock.h>

void print_memblock_ranges(void) {
struct memblock_region *reg;

for_each_mem_region(reg) {
printk("System RAM: %pa - %pa\n", &reg->base, &reg->base + reg->size - 1);
}
}

注意

  • 需内核配置CONFIG_HAVE_MEMBLOCK且保留memblock数据。
  • 主要适用于启动初期或特定调试场景。

总结

  • 推荐方法:使用资源树遍历或walk_iomem_res_desc,适用于大多数内核版本,安全可靠。
  • 早期内存信息:在合适场景下使用memblock,但需注意其可用性。
  • 同步机制:操作资源时确保加锁,避免竞态条件。

根据内核版本和具体需求选择最合适的方法。