linux内核分析之缺页中断(二)

本文详细阐述了在内核空间和用户空间中遇到非法访问时,系统如何通过`bad_area`函数进行处理。在用户空间访问时,直接发送`SEGSEGV`信号;而在内核空间访问时,若地址为错误的系统调用参数,则发送`SIGSEGV`信号,否则会显示内核的OOPS信息并终止进程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于缺页中断的非法访问由函数bad_area执行,该函数的执行情况分为:

1,如果在用户空间访问,直接发送SEGSEGV信号;

2,如果在内核空间访问分为两种情况:

1)地址是一个错误的系统调用参数,修正码(典型是发送SIGSEGV信号);

2)反之,杀死进程并显示内核的OOPS信息;

static void __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, unsigned long address, int si_code) { struct task_struct *tsk = current; /* User mode accesses just cause a SIGSEGV */ /*如果用户态*/ if (error_code & PF_USER) { /* * It's possible to have interrupts off here: */ local_irq_enable(); /* * Valid to do another page fault here because this one came * from user space: */ if (is_prefetch(regs, error_code, address)) return; if (is_errata100(regs, address)) return; if (unlikely(show_unhandled_signals)) show_signal_msg(regs, error_code, address, tsk); /* Kernel addresses are always protection faults: */ tsk->thread.cr2 = address; tsk->thread.error_code = error_code | (address >= TASK_SIZE); tsk->thread.trap_no = 14; /*发送SIGSEGV信号*/ force_sig_info_fault(SIGSEGV, si_code, address, tsk); return; } if (is_f00f_bug(regs, address)) return; /*内核态访问*/ no_context(regs, error_code, address); }

内核访问时

static noinline void no_context(struct pt_regs *regs, unsigned long error_code, unsigned long address) { struct task_struct *tsk = current; unsigned long *stackend; unsigned long flags; int sig; /* Are we prepared to handle this kernel fault? */ /*地址是一个系统调用参数,"修正码",典型情况是发送 SIGSEGV信号*/ if (fixup_exception(regs)) return; /* * 32-bit: * * Valid to do another page fault here, because if this fault * had been triggered by is_prefetch fixup_exception would have * handled it. * * 64-bit: * * Hall of shame of CPU/BIOS bugs. */ if (is_prefetch(regs, error_code, address)) return; if (is_errata93(regs, address)) return; /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice: */ /*下面代码用于oops信息的显示和杀死当前 进程*/ flags = oops_begin(); show_fault_oops(regs, error_code, address); stackend = end_of_stack(tsk); if (*stackend != STACK_END_MAGIC) printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); tsk->thread.cr2 = address; tsk->thread.trap_no = 14; tsk->thread.error_code = error_code; sig = SIGKILL; if (__die("Oops", regs, error_code)) sig = 0; /* Executive summary in case the body of the oops scrolled away */ printk(KERN_EMERG "CR2: %016lx\n", address); oops_end(flags, regs, sig); }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值