免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4496 | 回复: 8
打印 上一主题 下一主题

[内存管理] 关于内核空间缺页异常处理的一些疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-15 10:45 |只看该作者 |倒序浏览
有两个问题想请教下诸位
1.内核空间的缺页异常处理为什么只检查VMALLOC区域?也就是说内核只把VMALLOC区的异常视为一种“正常”的异常情况
2.关于spurious_fault()这个函数,看了下它内部只是做了些权限和页表项是否存在的检查,这个函数似乎是和TLB和页权限改变有关的,不是太明白,有哪位能帮忙说说么。
谢过

论坛徽章:
0
2 [报告]
发表于 2012-08-16 09:20 |只看该作者
一天了还没人呀……自己顶一个

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
3 [报告]
发表于 2012-08-16 10:40 |只看该作者
回复 1# VanBreaker

对于直接映射区,这个在系统启动时就populate了pgd,pmd,pte等,并进行了映射,所以不会page fault。

对于非连续内存区映射, ULK3上一段话:

一旦内核初始化阶段结束,任何进程或内核线程便都不直接使用主内核页表。因此,我们来考虑内核态进程对非连续内存区
的第一次访问。当把线性地址转换为物理地址时,CPU的内存管理单元遇到空的页表项并产生一个缺页。


进程在创建的时候拷贝的是kernel的pgd,所以在访问的时候pud,pmd,pte各项都要在需要的时候populate。

对于永久内核映射,临时内核映射,应该在需要的时候kmap,kmap_atomic一下,然后在访问吧。平时也用不到这段地址吧。


   

论坛徽章:
0
4 [报告]
发表于 2012-08-16 16:07 |只看该作者
先谢谢万鹏哥的回复,等了一天终于等到了-.-
我就觉得既然vmalloc区要被检查,那么永久内核映射区和临时内核映射区应该也要检查吧,万一这个触发异常的地址是属于这两个区域的话会怎么办呢……因为一旦他们映射了高端内存,那么对应的主内核页表项也应该就要修改了,而这种修改对进程的页表也同样是不可见的呀……只不过从大小来说,vmalloc区域要大得多。。。。
我在《深入LINUX内核架构》中翻到了这样一段解释内核缺页异常的话,提到了个这样的问题。。。“
“在向或从用户空间复制数据时,如果访问的地址在虚拟地址空间中不与物理内存页关联,则会发生缺页异常。对用户状态发生的该情况,我们已经熟悉。在应用程序访问一个虚拟地址时,内核将使用上文讨论的按需调页机制,自动并透明地返回一个物理内存页。日过访问发生在核心态,异常同样必须校正,但使用方法稍有不同。
    每次发生缺页异常时,将输出异常的原因和当前执行代码的地址。这使得内核可以编译一个列表,列出所有可能执行未授权内存访问操作的危险代码块……”
”后面就是对exception_fixup()机制的解释了。。难道说VMALLOC区域以外的异常都是通过exception_fixup()机制来处理的么……可惜小弟能力有限,看不太懂exception_fixup()的具体代码……

论坛徽章:
0
5 [报告]
发表于 2012-08-16 17:07 |只看该作者
回复 1# VanBreaker

我试着回答一下:

    1.内核空间的缺页异常处理为什么只检查VMALLOC区域?也就是说内核只把VMALLOC区的异常视为一种“正常”的异常情况


这个描述在哪里看到的?ARM的异常处理是这样的:
arch/arm/mm/fault.c
414 static int __kprobes
415 do_translation_fault(unsigned long addr, unsigned int fsr,
416                      struct pt_regs *regs)
。。。
423         if (addr < TASK_SIZE)
424                 return do_page_fault(addr, fsr, regs);
。。。
也就是说对于Kernel Space的处理的非线性映射区域(当然不仅仅是VMALLOC)都会做处理。处理的方式很简单,复制init_mm的即可。

至于以下帖子提到的fixup,处理的情况是在Kernel Mode 下触发 User Space异常。具体处理的策略是:谁触发,谁负责。你可以在Kernel Code下搜索一下.fixup section修饰的函数看看,实际上没有几处。另外,这个处理过程在毛德操的情景分析中,描述的非常好。你可以参考下。

第二个问题,提到的具体函数,我没有看过,不好意思。

论坛徽章:
0
6 [报告]
发表于 2012-08-16 19:36 |只看该作者
回复 5# omycle


    我看的是X86下的 do_page_fault()函数……我的意思是内核空间的异常为什么只检查VMALLOC区,而像永久内核映射区这样的区域为什么不用做检查。。ARM架构下的我没有看过。。
  1. if (unlikely(fault_in_kernel_space(address))) {
  2.                 if (!(error_code & (PF_RSVD | PF_USER | PF_PROT))) {
  3.                         if (vmalloc_fault(address) >= 0)
  4.                                 return;

  5.                         if (kmemcheck_fault(regs, address, error_code))
  6.                                 return;
  7.                 }

  8.                 /* Can handle a stale RO->RW TLB: */
  9.                 if (spurious_fault(error_code, address))
  10.                         return;

  11.                 /* kprobes don't want to hook the spurious faults: */
  12.                 if (notify_page_fault(regs))
  13.                         return;
  14.                 /*
  15.                  * Don't take the mm semaphore here. If we fixup a prefetch
  16.                  * fault we could otherwise deadlock:
  17.                  */
  18.                 bad_area_nosemaphore(regs, error_code, address);

  19.                 return;
  20.         }
复制代码

论坛徽章:
0
7 [报告]
发表于 2012-08-17 09:59 |只看该作者
回复 6# VanBreaker


   我猜想: 在X86平台中,Kernel Space的区域除了VMALLOC区外,其他区域都在初始化的时候被0号进程建立了映射。因此,就不需要在以后通过page fault机制进行同步了?

    可以看看代码是不是这样做的。

论坛徽章:
0
8 [报告]
发表于 2012-12-20 15:09 |只看该作者
arm平台的话,vmalloc、kmap、kmap_atomic都是修改的内核主页表内核空间部分映射,在系统访问上述方法分配的地址时,产生data abort/prefetch abort异常,在系统的异常处理过程中调用do_translation_fault函数,在此函数中完成内核主页表和task自己的页表的同步。
x86平台的话,需要看看kmap、kmap_atomic的实现,肯定有地方同步内核主页表和task自己的页表。

论坛徽章:
0
9 [报告]
发表于 2013-05-10 16:32 |只看该作者
这个问题很好,翻了一下代码,关于vmalloc缺页,而kmap不缺页的原因:
fork或者execv时拷贝了内核主页表的pgd条目(可理解为指针)。至于具体的pgd条目,指向的都是共享的pud,pmd,pte)
kmap在系统初始化时,就会一直分配到pte级,
所以后面fork或者execv出来的进程访问kmap空间不缺页,
但vmalloc会重新生成新的pgd条目 ,
所以后面的进程内核空间里没有这个地址空间,就会缺页。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP