0

0

Linux内存管理机制_虚拟内存与分页原理解析【教程】

舞夢輝影

舞夢輝影

发布时间:2025-12-30 19:47:02

|

645人浏览过

|

来源于php中文网

原创

Linux虚拟内存和分页是进程隔离的底层前提;CPU访问的是虚拟地址,MMU通过进程私有页表将其映射到不同物理页,缺页异常分软/硬/无效三类,多级页表兼顾稀疏空间与性能。

linux内存管理机制_虚拟内存与分页原理解析【教程】

Linux 的虚拟内存和分页不是“可选功能”,而是进程能独立运行、内存不互相踩踏的底层前提——关掉分页,连内核都起不来。

为什么每个进程看到的 0x7fff0000 都是自己的?

因为 CPU 访问的从来不是物理地址,而是线性地址(也叫虚拟地址)。分页机制在背后用 MMU 硬件单元实时做翻译:把进程 A 的 0x7fff0000 映射到物理内存的 0x1a2b3c00,同时把进程 B 的同个虚拟地址映射到 0x4d5e6f00。这个映射关系就存在每个进程私有的页表里。

常见错误现象:

  • 误以为 malloc 返回的指针是物理地址,试图用它直接操作硬件(实际会触发缺页异常或段错误)
  • 在内核模块里直接访问用户空间虚拟地址(没做 copy_from_useraccess_ok 检查),导致 Oops

关键点:

  • 用户态代码永远只能看到虚拟地址;/proc/pid/maps 显示的就是该进程当前有效的虚拟地址区间
  • 同一虚拟地址,在不同进程里映射的物理页可以完全不同,这是进程隔离的基石
  • 内核态有自己独立的页表(通常共享部分 PGD),但用户态页表切换由 CR3 寄存器控制,每次进程切换时刷新

缺页异常(Page Fault)不是 bug,是正常流程

当进程首次访问某块虚拟内存(比如刚 mmap 的文件区域,或第一次写 malloc 出来的内存),对应页表项还是空的,CPU 就会触发 #PF 异常,交由内核的 do_page_fault() 处理。

它分三种典型情况:

  • 软缺页(Soft Page Fault):页已在内存中(如共享库代码页),只是当前进程页表还没建立映射,内核只需填好 PTE,开销极小
  • 硬缺页(Hard Page Fault):页在磁盘交换区或文件中,需从磁盘读入,耗时毫秒级,是性能瓶颈常见来源
  • 无效缺页(Invalid Fault):访问未分配/无权限地址(如 NULL 指针解引用、只读页写入),内核发 SEGV 信号终止进程

实操建议:

  • perf stat -e page-faults,minor-faults,major-faults ./your_program 区分软硬缺页比例
  • 频繁 major-faults 往往说明物理内存不足,或程序局部性差(随机访问大文件)
  • 避免在 tight loop 中反复 mmap/munmap,这会不断触发软缺页并增加 TLB 压力

多级页表不是为了炫技,是为省内存和适配稀疏地址空间

32 位系统若用单级页表,4GB 地址空间 / 4KB 每页 = 1048576 个页表项,每个 4 字节 → 要占满 4MB 连续物理内存。而现实中一个普通进程只用几 MB 虚拟内存,且高度分散(代码段、堆、、mmap 区各占一块)。多级页表(x86-64 是 4 级:PGD → P4D → PMD → PTE)只分配实际用到的路径节点。

Lateral App
Lateral App

整理归类论文

下载

容易踩的坑:

  • 误以为“级数越多越慢”——现代 CPU 的 TLB(Translation Lookaside Buffer)会缓存多级转换结果,只要命中 TLB,速度和单级无异
  • 在嵌入式场景强行启用 4K 页,却忽略 ARM64 支持 64KB 大页,对大内存服务(如数据库)可显著减少 TLB miss 和页表遍历开销
  • 调试时看 /proc/pid/statusMMUPageSize 并不反映实际页大小,要查 /sys/kernel/mm/transparent_hugepage 或用 cat /proc/pid/smaps | grep -i "mmu.*page"

如何验证某个虚拟地址是否已映射到物理内存?

不能靠 cat /proc/pid/pagemap 直接读,因为该接口需要 root 权限,且返回的是 64 位帧号(PFN),还需结合 /proc/kpageflags 判断是否 present、swap、soft-dirty 等状态。

更实用的做法:

  • mincore() 系统调用检查某段虚拟内存是否驻留在 RAM 中(注意:只对匿名映射或 mmap 文件有效,且需先 mlock 或触发过访问)
  • 在调试中,用 pstack + gdb attach 查看 info proc mappings,再配合 cat /proc/pid/pagemap(需 root)解析特定地址
  • 观察 /proc/pid/statm 的第 2 列(resident):单位是页,即当前驻留物理内存的页数

示例(检查进程 1234 的 0x7ffff7ffa000 是否在内存):

python3 -c "
import struct
with open('/proc/1234/pagemap', 'rb') as f:
    f.seek(0x7ffff7ffa000 // 0x1000 * 8)
    entry = struct.unpack('Q', f.read(8))[0]
    print('Present:', bool(entry & (1<<63)))
    print('Page Frame Number:', entry & ((1<<55)-1))
"

注意:该脚本需 root 运行,且目标进程不能被 ptrace 保护(ptrace_scope=1 时受限)。

真正复杂的地方在于:页表项本身可能被换出、被 KSM 合并、被透明大页拆分、甚至被 CMA 预留区绕过——这些都不是靠读一个文件就能说清的,得结合具体内核版本和配置来看。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

228

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

433

2024.03.01

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

989

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

49

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

164

2025.12.29

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

366

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

559

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

366

2023.07.18

桌面文件位置介绍
桌面文件位置介绍

本专题整合了桌面文件相关教程,阅读专题下面的文章了解更多内容。

0

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.2万人学习

Git 教程
Git 教程

共21课时 | 2.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号