分类: LINUX
2012-06-21 10:03:46
对于缺页中断的非法访问由函数bad_area执行,该函数的执行情况分为:
1,如果在用户空间访问,直接发送SEGSEGV信号;
2,如果在内核空间访问分为两种情况:
1)地址是一个错误的系统调用参数,修正码(典型是发送SIGSEGV信号);
2)反之,杀死进程并显示内核的OOPS信息;
[cpp] view plaincopyprint?
1. static void
2. __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
3. unsigned long address, int si_code)
4. {
5. struct task_struct *tsk = current;
6.
7. /* User mode accesses just cause a SIGSEGV */
8. /*如果用户态*/
9. if (error_code & PF_USER) {
10. /*
11. * It's possible to have interrupts off here:
12. */
13. local_irq_enable();
14.
15. /*
16. * Valid to do another page fault here because this one came
17. * from user space:
18. */
19. if (is_prefetch(regs, error_code, address))
20. return;
21.
22. if (is_errata100(regs, address))
23. return;
24.
25. if (unlikely(show_unhandled_signals))
26. show_signal_msg(regs, error_code, address, tsk);
27.
28. /* Kernel addresses are always protection faults: */
29. tsk->thread.cr2 = address;
30. tsk->thread.error_code = error_code | (address >= TASK_SIZE);
31. tsk->thread.trap_no = 14;
32. /*发送SIGSEGV信号*/
33. force_sig_info_fault(SIGSEGV, si_code, address, tsk);
34.
35. return;
36. }
37.
38. if (is_f00f_bug(regs, address))
39. return;
40. /*内核态访问*/
41. no_context(regs, error_code, address);
42. }
内核访问时
[cpp] view plaincopyprint?
1. static noinline void
2. no_context(struct pt_regs *regs, unsigned long error_code,
3. unsigned long address)
4. {
5. struct task_struct *tsk = current;
6. unsigned long *stackend;
7. unsigned long flags;
8. int sig;
9.
10. /* Are we prepared to handle this kernel fault? */
11. /*地址是一个系统调用参数,"修正码",典型情况是发送
12. SIGSEGV信号*/
13. if (fixup_exception(regs))
14. return;
15.
16. /*
17. * 32-bit:
18. *
19. * Valid to do another page fault here, because if this fault
20. * had been triggered by is_prefetch fixup_exception would have
21. * handled it.
22. *
23. * 64-bit:
24. *
25. * Hall of shame of CPU/BIOS bugs.
26. */
27. if (is_prefetch(regs, error_code, address))
28. return;
29.
30. if (is_errata93(regs, address))
31. return;
32.
33. /*
34. * Oops. The kernel tried to access some bad page. We'll have to
35. * terminate things with extreme prejudice:
36. */
37. /*下面代码用于oops信息的显示和杀死当前
38. 进程*/
39. flags = oops_begin();
40.
41. show_fault_oops(regs, error_code, address);
42.
43. stackend = end_of_stack(tsk);
44. if (*stackend != STACK_END_MAGIC)
45. printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
46.
47. tsk->thread.cr2 = address;
48. tsk->thread.trap_no = 14;
49. tsk->thread.error_code = error_code;
50.
51. sig = SIGKILL;
52. if (__die("Oops", regs, error_code))
53. sig = 0;
54.
55. /* Executive summary in case the body of the oops scrolled away */
56. printk(KERN_EMERG "CR2: %016lx\n", address);
57.
58. oops_end(flags, regs, sig);
59. }