Page Fault vs Segmentation Fault:真正的区别与内核处理流程


支持作者,点击京东购买《Yocto项目实战教程》


Page Fault vs Segmentation Fault:真正的区别与内核处理流程

在 Linux 系统中,很多人在程序崩溃时会看到熟悉的错误信息:

Segmentation fault (core dumped)

这似乎说明程序出现了“内存访问错误”。但背后到底发生了什么?这和操作系统中的 Page Fault(页错误) 有什么关系?

本文将从概念、触发流程、内核代码处理、异常信号以及实际案例来全面剖析 Page Fault 与 Segmentation Fault 的本质区别与联系,帮助读者理解它们在 Linux 内核中的真实工作机制。


一、概念清晰化:Page Fault 与 Segmentation Fault

✅ Page Fault 是什么?

Page Fault 是一种 正常的中断机制,指的是程序访问了一个尚未映射物理页帧的虚拟地址时,由硬件(CPU)向操作系统发出的中断。

这通常发生在:

  • 第一次访问 malloc/mmap 分配的内存
  • 栈自动增长
  • 读取换出到磁盘的页(swap-in)

如果地址合法,操作系统会分配页帧或执行换页操作,处理完毕后程序继续执行
在这里插入图片描述

❌ Segmentation Fault 是什么?

Segmentation Fault 是一种 严重的内存访问错误,指程序访问了不允许访问的虚拟地址或具有不当权限的地址,内核判定为非法后发出 SIGSEGV 信号,导致程序崩溃。

常见原因:

  • 访问 NULL 指针(0x0 地址)
  • 数组越界访问未映射页
  • 写入只读内存区域(如 .text 段)
  • 释放后访问(use-after-free)

二、关系揭示:它们之间是什么关系?

✅ 一句话总结:

所有 Segmentation Fault 都是 Page Fault,但不是所有 Page Fault 都是 Segmentation Fault。

  • Page Fault 是机制,属于访问虚拟页时的一次页表异常
  • Segmentation Fault 是后果,是非法 Page Fault 的处理结果

三、实际流程解析:一次 Page Fault 的内核处理路径

以 x86_64 架构为例,当用户态程序访问虚拟地址时:

  1. CPU 检查页表,发现页未映射,触发中断 #PF(Page Fault)

  2. 进入内核:

    do_page_fault(struct pt_regs *regs, unsigned long address, unsigned int error_code);
    
  3. 内核检查该地址是否属于合法区间(如 VMA)

  4. 如果合法:

    • 调用 handle_mm_fault()alloc_pages() → 建立映射 → 返回用户态
  5. 如果非法:

    • 调用 bad_area() → 向进程发送 SIGSEGV

四、代码级逻辑核心函数一览

函数名作用说明
do_page_fault()Page Fault 异常入口函数
find_vma()查找虚拟地址是否落入合法区间
handle_mm_fault()执行缺页处理(如分配页、换页等)
vmalloc_fault()处理 vmalloc 虚拟区间的特例 fault
bad_area()地址非法或权限错误,生成 SIGSEGV 信号
force_sig_info()向当前进程发送 SIGSEGV 信号

五、典型案例:正常 Page Fault vs 错误 Page Fault

✅ 案例1:合法缺页

char *buf = malloc(4096);
buf[0] = 'A';  // 第一次写,触发合法 Page Fault
  • malloc() 仅创建虚拟地址映射;
  • 第一次访问时触发 Page Fault,内核分配页帧;
  • 返回后程序继续运行。

❌ 案例2:非法访问

char *p = NULL;
*p = 1;  // Segmentation Fault
  • NULL 是无效地址(0x0)
  • Page Fault 发生 → 地址不合法 → 触发 SIGSEGV

六、信号机制与用户态结果

当 Segmentation Fault 发生时,内核向进程发送:

SIGSEGV(信号编号 11)

默认行为:终止进程并生成 core dump,可通过 ulimit -c unlimited 启用。

程序崩溃提示:

Segmentation fault (core dumped)

可以用 gdb ./a.out core 调试查看崩溃位置。


七、与调试工具的联动:perf + crash + ftrace

工具用途
perf分析 page-fault 热点函数位置
ftrace跟踪 handle_mm_fault / do_page_fault 调用链
crash在内核崩溃时检查进程页表、VMA 信息

八、总结回顾

对比点Page FaultSegmentation Fault
是否是错误❌ 不一定✅ 是非法访问
由谁处理内核页异常处理函数内核产生 SIGSEGV 信号
是否可恢复✅ 可以(合法地址)❌ 不可恢复(直接终止进程)
是否导致崩溃❌ 不一定✅ 通常导致程序崩溃

九、一句话总结

Page Fault 是虚拟地址管理的调度机制,而 Segmentation Fault 是非法内存访问的结果。在 Linux 内核中,二者一脉相承,却职责不同,掌握它们的区别是理解 Linux 内存系统和调试问题的核心基础。


支持作者,点击京东购买《Yocto项目实战教程》


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值