人固有一死或重于泰山或轻于鸿毛,死法不一殊途同归,留下的是后人的精神瞻仰。linux系统在某些异常情况产生之后会选择“死去”,来看下它是如何死去的。
linux version:4.14.224
arch:mips
file:arch\mips\kernel\traps.c
traps.c有个die函数:
void __noreturn die(const char *str, struct pt_regs *regs)
{
static int die_counter; //die函数调用计数
int sig = SIGSEGV; //SIGSEGV是当一个应用层进程执行了一个无效的内存引用,或发生段错误时发送给它的信号
oops_enter(); //进入oops
if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_nr,
SIGSEGV) == NOTIFY_STOP) //通知DIE_OOPS消息,注册了此消息的模块会受到此事件
sig = 0;
console_verbose(); //终端详细输出
raw_spin_lock_irq(&die_lock); //上锁
bust_spinlocks(1); //忽略所有lock详见bust spinlocks机制
printk("%s[#%d]:\n", str, ++die_counter); //打印“死”原因及第几次“死”
show_registers(regs); //打印模块、进程、寄存器、栈、错误码等信息
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); //添加内核污染标志,表示内核出错状态
raw_spin_unlock_irq(&die_lock); //解锁
oops_exit(); //退出oops
if (in_interrupt()) //判断当前进程是否处于中断上下文,这个中断上下文包括底半部和硬件中断处理过程
panic("Fatal exception in interrupt"); //panic
if (panic_on_oops) //panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE;oops会不会panic的配置
panic("Fatal exception"); //panic
if (regs && kexec_should_crash(current)) //检测当前进程是否应该崩溃
crash_kexec(regs); //执行内核崩溃重启动转存储捕捉内核
do_exit(sig); //退出进程
}
void oops_enter(void)
{
tracing_off();
/* can't trust the integrity of the kernel anymore: */
debug_locks_off();
do_oops_enter_exit();
}
void oops_exit(void)
{
do_oops_enter_exit();
print_oops_end_marker();
kmsg_dump(KMSG_DUMP_OOPS);
}
void show_registers(struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
mm_segment_t old_fs = get_fs();
__show_regs(regs);
print_modules();
printk("Process %s (pid: %d, threadinfo=%p, task=%p, tls=%0*lx)\n",
current->comm, current->pid, current_thread_info(), current,
field, current_thread_info()->tp_value);
if (cpu_has_userlocal) {
unsigned long tls;