操作系统番外2(Linux的虚拟内存)(TODO)
(TODO)
在 Linux 中,虚拟内存不仅仅是地址转换,它是一套复杂的资源管理机制。以下是作为 BSP 工程师最需要掌握的核心概念和调试手段。
1. Linux 虚拟内存布局 (Memory Layout)
Linux 将虚拟地址空间划分为两大部分:用户空间 (User Space) 和 内核空间 (Kernel Space)。
-
用户空间:每个进程都有独立的 $2^{N}$ 虚拟空间(32位系统为 3GB,64位系统巨大)。
-
内核空间:所有进程共享同一个内核映射。
-
Lowmem (直接映射区):物理内存的前一部分直接线性映射到内核虚拟地址。
-
Vmalloc 区:用于非连续物理内存的映射,适合分配大块缓冲区。
-
2. 核心机制:从“静态映射”到“动态按需”
你在裸机中可能是预先写死页表,而 Linux 是 “按需分页” (Paging on demand):
-
页表 (Page Tables):Linux 使用多级页表(如 ARM64 通常是 4 级:PGD -> PUD -> PMD -> PTE)。
-
缺页异常 (Page Fault):当你访问一个尚未建立映射的虚拟地址时,内核会触发缺页异常,在异常处理函数中实时分配物理页并填充页表。
3. BSP 工程师必看的内存节点
在调试 Camera 数据流或大块 DMA 缓冲区时,你需要通过以下节点监控内存状态。
/proc/meminfo (全局视角)
-
用途:查看系统总内存使用情况。
-
关键指标:
-
MemTotal: 总物理内存。 -
MemAvailable: 真正可用的内存(比Free更准确,因为它计入了可回收的 Cache)。 -
AnonPages: 进程使用的匿名内存(堆、栈)。
-
/proc# cat /proc/meminfo
ShmemPmdMapped: 0 kB
FileHugePages: 0 kB
FilePmdMapped: 0 kB
CmaTotal: 0 kB
CmaFree: 0 kB
Unaccepted: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
DirectMap4k: 66332 kB
DirectMap2M: 5173248 kB
DirectMap1G: 10485760 kB
/proc/[pid]/maps & smaps (进程视角)
-
用途:查看某个具体进程(如你的 AI 视觉处理进程)的内存映射。
-
实战:通过
cat /proc/self/maps可以看到代码段、数据段、堆以及共享库(.so)分别映射在什么虚拟地址。
/proc# cat 10143/maps
59865aa00000-59865aa19000 r--p 00000000 07:00 1049563 /usr/bin/tmux
59865aa19000-59865aab0000 r-xp 00019000 07:00 1049563 /usr/bin/tmux/lib/x86_64-linux-gnu/libevent_core-2.1.so.7.0.1
7d00df3d7000-7d00df3e5000 r--p 00000000 07:00 5112886 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.3
7d00df3e5000-7d00df3f6000 r-xp 0000e000 07:00 5112886 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.3
7d00df3f6000-7d00df404000 r--p 0001f000 07:00 5112886 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.3
7d00df404000-7d00df408000 r--p 0002c000 07:00 5112886 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.3
7d00df408000-7d00df409000 rw-p 00030000 07:00 5112886 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.3
7d00df409000-7d00df40a000 r--p 00000000 07:00 1079497 /usr/lib/x86_64-linux-gnu/libutempter.so.1.2.1
7d00df40a000-7d00df40b000 r-xp 00001000 07:00 1079497 /usr/lib/x86_64-linux-gnu/libutempter.so.1.2.1
7d00df40b000-7d00df40c000 r--p 00002000 07:00 1079497 /us
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7d00df44a000-7d00df455000 r--p 0002c000 07:00 5112750 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7d00df456000-7d00df458000 r--p 00037000 07:00 5112750 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7d00df458000-7d00df45a000 rw-p 00039000 07:00 5112750 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffc9b7c1000-7ffc9b7e2000 rw-p 00000000 00:00 0 [stack]
7ffc9b7ec000-7ffc9b7f0000 r--p 00000000 00:00 0 [vvar]
7ffc9b7f0000-7ffc9b7f2000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
/proc/buddyinfo (物理内存碎片)
-
用途:查看内核伙伴系统(Buddy System)的空闲页分布。
-
排查逻辑:如果你在 Bring-up 驱动时发现
kmalloc分配大块内存失败,即使总内存够用,看这里也能发现是否是因为内存碎片严重(高 order 的空闲块为 0)。
4. 驱动开发中的关键接口
你在做 BSP 调试时,经常会用到这几个函数,它们是操作虚拟内存的“抓手”:
-
ioremap():-
场景:将硬件寄存器的物理地址(PA)映射到内核虚拟地址(VA),以便 CPU 读写寄存器。
-
-
mmap()(用户态):-
场景:将设备内存(如 Camera Buffer)直接映射到用户空间,实现零拷贝 (Zero-copy)。
-
-
dma_alloc_coherent():-
场景:分配物理连续且关闭 Cache 的内存,用于 DMA 传输。
-
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)