ARM Linux异常处理之data abort
时间:11-09
来源:互联网
点击:
ission fault" },{ do_bad, SIGBUS, 0, "external abort on translation" },{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },{ do_bad, SIGBUS, 0, "unknown 16" },// 。。。{ do_bad, SIGBUS, 0, "unknown 30" },{ do_bad, SIGBUS, 0, "unknown 31" }};fsr_info对大多数abort都调用do_bad函数处理,do_bad函数简单返回1,这样就可以继续执行上面提到的arm_notify_die。
fsr_info对以下四种特殊abort将作单独处理:
__do_kernel_fault则比较复杂:
Linux产生段表错误,除了fixup之外还有两种原因:一个是用户空间映射的线性地址出现异常,另一个是内核中调用vmalloc分配的线性地址出现异常。对用户空间地址的异常处理很容易理解。对于内核地址,从vmalloc的实现代码中可以看到,它分配的线性空间的映射关系都会保存到全局变量init_mm中,所以,任何vmalloc生成的线性空间的二级页表都应该在init_mm中找到。(init_mm是内核的mm_struct,管理整个内核的内存映射)。
从这里也可以看出,对vmalloc的地址访问可能会产生两次异常:第一次是段表错误,生成二级页表;第二次是页表错误,分配真正的物理页面到线性空间。
5.5 页表错误 do_page_fault
do_page_fault完成了真正的物理页面分配工作,另外栈扩展、mmap的支持等也都在这里。对于物理页面的分配,会调用到do_anonymous_page->。。。-> __rmqueue,__rmqueue中实现了物理页面分配的伙伴算法。
如果当前没有足够物理页面供内存分配,即分配失败:
fsr_info对以下四种特殊abort将作单独处理:
- "section translation fault" do_translation_fault
- "page translation fault" do_page_fault
- "section permission fault" do_sect_fault
- "page permission fault" do_page_fault
5.3 段权限错误 do_sect_fault
do_sect_fault函数直接调用do_bad_area作处理,并返回0,所以不会再经过arm_notify_die。do_bad_area中,判断是否属于用户模式。如果是用户模式,调用__do_user_fault函数;否则调用__do_kernel_fault函数。void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)if (user_mode(regs))__do_user_fault(tsk, addr, fsr, SIGSEGV, SEGV_MAPERR, regs);else__do_kernel_fault(mm, addr, fsr, regs);__do_user_fault中,会发送信号给当前线程。
__do_kernel_fault则比较复杂:
- 调用fixup_exception进行修复操作,fixup的具体细节可在内核文档exception.txt中找到,它可用于处理get_user之类函数传入的地址参数无效的情况。
- 如果不能修复,调用die函数处理oops。
- 如果没有进程上下文,内核会在上一步的oops中panic。所以到这里肯定有一个进程与之关联,于是调用do_exit(SIGKILL)函数退出进程,SIGKILL会被设置在task_struct的exit_code域。
5.4 段表错误 do_translation_fault
do_translation_fault函数中,会首先判断引起abort的地址是否处于用户空间。- 如果是用户空间地址,调用do_page_fault,转入和页表错误、页权限错误同样的处理流程。
- 如果是内核空间地址,会判断该地址对应的二级页表指针是否在init_mm中。如果在init_mm里面,www.linuxidc.com那么该二级页表指针到当前进程的一级页表;否则,调用do_bad_area处理(可能会调用到fixup)。
Linux产生段表错误,除了fixup之外还有两种原因:一个是用户空间映射的线性地址出现异常,另一个是内核中调用vmalloc分配的线性地址出现异常。对用户空间地址的异常处理很容易理解。对于内核地址,从vmalloc的实现代码中可以看到,它分配的线性空间的映射关系都会保存到全局变量init_mm中,所以,任何vmalloc生成的线性空间的二级页表都应该在init_mm中找到。(init_mm是内核的mm_struct,管理整个内核的内存映射)。
从这里也可以看出,对vmalloc的地址访问可能会产生两次异常:第一次是段表错误,生成二级页表;第二次是页表错误,分配真正的物理页面到线性空间。
5.5 页表错误 do_page_fault
5.6 页权限错误 do_page_fault
do_page_fault完成了真正的物理页面分配工作,另外栈扩展、mmap的支持等也都在这里。对于物理页面的分配,会调用到do_anonymous_page->。。。-> __rmqueue,__rmqueue中实现了物理页面分配的伙伴算法。如果当前没有足够物理页面供内存分配,即分配失败:
- 内核模式下的abort会调用__do_kernel_fault,这与段权限错误中的处理一样。
- 用户模式下,会调用do_group_exit退出该任务所属的进程。
ARMLinux异常处理dataabor 相关文章:
- ARM Linux异常处理之data abort二(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)