在阅读协议栈代码(内核版本2.6.38),在很多地方都看到panic调用,只是知道大体功能,从未具体分析过,也一直想把协议栈的分析过程写下来,很懒,就一有写,算今天是个开始吧。分析panic太艰难啦,涉及的东西太多啦。
- /**
- * panic - halt the system
- * @fmt: The text string to print
- *
- * Display a message, then perform cleanups.
- *
- * This function never returns.
- */
- NORET_TYPE void panic(const char * fmt, ...)
- {
- static char buf[1024];
- va_list args;
- long i, i_next = 0;
- int state = 0;
-
- /*
- * It's possible to come here directly from a panic-assertion and
- * not have preempt disabled. Some functions called from here want
- * preempt to be disabled. No point enabling it later though...
- */
- /**
- * 英文注释已经很清晰啦,就是在panic执行过程CPU不能被抢占。
- */
- preempt_disable();
- /**
- * 修改console 级别,以便printk能把消息打印出来。
- */
- console_verbose();
- /*
- * Unlock any spinlocks which will prevent
- * us from getting the
- message out.
- * 英文注释没有看多大明白啊,大概意思好像是抑制打印。
- */
- bust_spinlocks(1);
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
- #ifdef CONFIG_DEBUG_BUGVERBOSE
- dump_stack();
- #endif
-
- /*
- * If we have crashed and we have a crash kernel loaded let it handle
- * everything else.
- * Do we want to call this before we try to display a message?
- */
- crash_kexec(NULL);
- /××
- × 应该主要是dump CPU寄存器的状态值已经一些堆栈的信息。
- ×/
- kmsg_dump(KMSG_DUMP_PANIC);
-
- /*
- * Note smp_send_stop is the usual smp shutdown function, which
- * unfortunately means it may not be hardened to work in a panic
- * situation.
- */
- smp_send_stop();
- /××
- × 调用注册到panic时需要特殊处理的函数,如kgdb调试的入口等,
- ×/
- atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
-
- bust_spinlocks(0);
-
- if (!panic_blink)
- panic_blink = no_blink;
/**
* 如果sysctl配置了panic_timeout > 0则在panic_timeout后重 * 启系统
*/
- if (panic_timeout > 0) {
- /*
- * Delay timeout seconds before rebooting the machine.
- * We can't use the "normal" timers since we just panicked.
- */
- printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout);
-
- for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {
- touch_nmi_watchdog();
- if (i >= i_next) {
- i += panic_blink(state ^= 1);
- i_next = i + 3600 / PANIC_BLINK_SPD;
- }
- mdelay(PANIC_TIMER_STEP);
- }
- /*
- * This will not be a clean reboot, with everything
- * shutting down. But if there is a chance of
- * rebooting the system it will be rebooted.
- */
- emergency_restart();
- }
- #ifdef __sparc__
- {
- extern int stop_a_enabled;
- /* Make sure the user can actually press Stop-A (L1-A) */
- stop_a_enabled = 1;
- printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n");
- }
- #endif
- #if defined(CONFIG_S390)
- {
- unsigned long caller;
-
- caller = (unsigned long)__builtin_return_address(0);
- disabled_wait(caller);
- }
- #endif
- local_irq_enable();
- /**
- * 进行死循环,抢占被禁止,CPU一直运行panic程序中运行。
- */
- for (i = 0; ; i += PANIC_TIMER_STEP) {
- touch_softlockup_watchdog();
- if (i >= i_next) {
- i += panic_blink(state ^= 1);
- i_next = i + 3600 / PANIC_BLINK_SPD;
- }
- mdelay(PANIC_TIMER_STEP);
- }
- }
文章出处:http://blog.chinaunix.net/uid-20599901-id-272235.html