/proc/iomem 是 Linux 系统物理地址空间布局的权威运行时视图,以“起始-结束地址 : 描述”格式列出 System RAM、reserved、PCI Bus、ACPI Tables 等区域,其中仅顶层未缩进且标注“System RAM”的条目才表示内核可管理的物理内存块,多段可能不连续;它不同于 dmesg 中的 e820 启动映射(更贴近硬件)和 /proc/meminfo 中的 MemTotal(仅总量无地址),也不反映用户可用虚拟内存。

/proc/iomem 是查看 Linux 系统物理内存布局最直接、最权威的入口,它反映的是内核视角下整个物理地址空间的划分,包括 System RAM、保留区、PCI 设备映射、ACPI 表等。不是所有“内存起始地址”都指用户可用 RAM 的起点——真正能被 malloc 或进程使用的,只是其中一部分。
直接读取 /proc/iomem 并识别 System RAM
执行 cat /proc/iomem 后,关键是要过滤出带 System RAM 标签的行:
- 输出中每行格式为
<起始地址>-<结束地址> : <描述>,例如00000000-0009ffff : System RAM表示从物理地址0x0开始的一段可用内存 - 现代系统(尤其是 UEFI 启动)通常有多个
System RAM区域,可能不连续,比如80000000-9effffff : System RAM和c0000000-cfffffff : System RAM - 注意缩进:子区域(如 PCI Bus 下的设备)是嵌套结构,但只有顶层带
System RAM的才表示物理内存块 - 不要混淆
reserved、Kernel code、Kernel data—— 它们虽在 RAM 地址范围内,但已被内核静态占用,不可用于用户态分配
用 dmesg | grep -i "e820\|memory" 验证启动时的原始内存图
/proc/iomem 是运行时视图,而 dmesg 输出的是内核启动阶段通过 BIOS/UEFI 获取的原始内存布局(e820 map),更接近硬件真实情况:
-
dmesg | grep -i e820会显示类似[ 0.000000] e820: BIOS-provided physical RAM map:及后续条目,列出所有已报告的 RAM 段 - 若发现某段
System RAM在/proc/iomem中缺失,很可能是被内核 early-reserve、kdump 预留或 firmware 保留掉了,此时dmesg更可信 - 某些嵌入式平台(如 ARM64)可能不输出 e820,改用
mem=内核参数或 device tree 信息,此时应配合cat /proc/meminfo | grep MemTotal做交叉验证
别把 free 或 /proc/meminfo 当作物理地址来源
这两个命令只告诉你“有多少内存可用”,完全不提供物理地址信息:
-
free -h显示的是内核管理下的可用页数,单位是字节,没有地址维度 -
/proc/meminfo中的MemTotal是总可用物理页大小(KB),但不等于/proc/iomem中所有System RAM区域之和——因为部分 RAM 被标记为reserved或未被内核纳入管理(如被 vgaarb、iommu 或 secure boot 锁定) - 试图从
MemTotal反推起始地址是徒劳的;物理地址必须来自/proc/iomem或dmesg的原始映射
需要精确到某个设备寄存器?优先查 /proc/iomem + lspci -vv
如果你实际想定位网卡、GPU 或其他外设的 MMIO 寄存器物理地址,/proc/iomem 仍是第一站,但需结合设备枚举:
- 先用
lspci -vv找到目标设备(如0000:01:00.0),看其Memory at行,例如Memory at e0000000 (64-bit, prefetchable) - 再回查
/proc/iomem,找是否有一行以e0000000-开头并归属PCI Bus或具体设备名(如0000:01:00.0) - 注意:有些设备驱动会主动隐藏其资源(如使用
iomem=参数屏蔽),此时/proc/iomem不显示,但lspci仍可见——说明该区域未被内核 resource 子系统接管,不能直接ioremap
真正容易被忽略的是:同一物理地址段在不同上下文里含义不同。比如 0x80000000 在 /proc/iomem 中是 RAM 起点,在 lspci 输出里可能是显卡显存起点,而在 bootloader 日志里又可能是 kernel image 加载地址——它们共享地址空间,但归属和访问方式完全不同。


















