欢迎光临散文网 会员登陆 & 注册

一文读懂linux缺页异常处理--内核空间(技术干货~)

2022-06-09 16:27 作者:补给站Linux内核  | 我要投稿
  • 缺页异常被触发通常有两种情况

  1. 程序设计的不当导致访问了非法的地址

  2. 访问的地址是合法的,但是该地址还未分配物理页框


  • 下面解释一下第二种情况,这是虚拟内存管理的一个特性。尽管每个进程独立拥有3GB的可访问地址空间,但是这些资源都是内核开出的空头支票,也就是说进程手握着和自己相关的一个个虚拟内存区域(vma),但是这些虚拟内存区域并不会在创建的时候就和物理页框挂钩,由于程序的局部性原理,程序在一定时间内所访问的内存往往是有限的,因此内核只会在进程确确实实需要访问物理内存时才会将相应的虚拟内存区域与物理内存进行关联(为相应的地址分配页表项,并将页表项映射到物理内存),也就是说这种缺页异常是正常的,而第一种缺页异常是不正常的,内核要采取各种可行的手段将这种异常带来的破坏减到最小。

  • 缺页异常的处理函数为do_page_fault(),该函数是和体系结构相关的一个函数,缺页异常的来源可分为两种,一种是内核空间(访问了线性地址空间的第4个GB),一种是用户空间(访问了线性地址空间的0~3GB),以X86架构为例,先来看内核空间异常的处理。

  • 该函数传递进来的两个参数

  1. regs包含了各个寄存器的值

  2. error_code是触发异常的错误类型,它的含义如下

【文章福利】小编推荐自己的Linux内核技术交流群:【891587639】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!(含视频教程、电子书、实战项目及代码)    

首先要检查该异常的触发地址是不是位于内核地址空间 也就是address>=TASK_SIZE_MAX,一般为3GB。然后要检查触发异常时是否处于内核态,满足这两个条件就尝试通过vmalloc_fault()来解决这个异常。由于使用vmalloc申请内存时,内核只会更新主内核页表,所以当前使用的进程页表就有可能因为未与主内核页表同步导致这次异常的触发,因此该函数试图将address对应的页表项与主内核页表进行同步

同步处理:

  • 如果do_page_fault()函数执行到了bad_area_nosemaphore(),那么就表明这次异常是由于对非法的地址访问造成的。在内核中产生这样的结果的情况一般有两种:

  1. 内核通过用户空间传递的系统调用参数,访问了无效的地址

  2. 内核的程序设计缺陷

  • 第一种情况内核尚且能通过异常修正机制来进行修复,而第二种情况就会导致OOPS错误了,内核将强制用SIGKILL结束当前进程。

  • 内核态的bad_area_nosemaphore()的实际处理函数为bad_area_nosemaphore()-->__bad_area_nosemaphore()-->no_context()


一文读懂linux缺页异常处理--内核空间(技术干货~)的评论 (共 条)

分享到微博请遵守国家法律