Kernel函数解析之panic

位置:panic()函数在panic.c文件中,该文件位于kernel/目录下;

作用:该函数的主要作用是停止当前的系统运行,供系统监测到异常时调用。

流程:

 【源码】:


   
   
  1. /**
  2. * panic - halt the system
  3. * @fmt: The text string to print
  4. *
  5. * Display a message, then perform cleanups.
  6. *
  7. * This function never returns.
  8. */
  9. void panic( const char *fmt, ...)
  10. {
  11. static char buf[ 1024];
  12. va_list args;
  13. long i, i_next = 0, len;
  14. int state = 0;
  15. int old_cpu, this_cpu;
  16. bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers;
  17. /*
  18. * Disable local interrupts. This will prevent panic_smp_self_stop
  19. * from deadlocking the first cpu that invokes the panic, since
  20. * there is nothing to prevent an interrupt handler (that runs
  21. * after setting panic_cpu) from invoking panic() again.
  22. */
  23. local_irq_disable();
  24. preempt_disable_notrace();
  25. /*
  26. * It's possible to come here directly from a panic-assertion and
  27. * not have preempt disabled. Some functions called from here want
  28. * preempt to be disabled. No point enabling it later though...
  29. *
  30. * Only one CPU is allowed to execute the panic code from here. For
  31. * multiple parallel invocations of panic, all other CPUs either
  32. * stop themself or will wait until they are stopped by the 1st CPU
  33. * with smp_send_stop().
  34. *
  35. * `old_cpu == PANIC_CPU_INVALID' means this is the 1st CPU which
  36. * comes here, so go ahead.
  37. * `old_cpu == this_cpu' means we came from nmi_panic() which sets
  38. * panic_cpu to this CPU. In this case, this is also the 1st CPU.
  39. */
  40. this_cpu = raw_smp_processor_id();
  41. old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu);
  42. if (old_cpu != PANIC_CPU_INVALID && old_cpu != this_cpu)
  43. panic_smp_self_stop();
  44. console_verbose();
  45. bust_spinlocks( 1);
  46. va_start(args, fmt);
  47. len = vscnprintf(buf, sizeof(buf), fmt, args);
  48. va_end(args);
  49. if (len && buf[len - 1] == '\n')
  50. buf[len - 1] = '\0';
  51. pr_emerg( "Kernel panic - not syncing: %s\n", buf);
  52. #ifdef CONFIG_DEBUG_BUGVERBOSE
  53. /*
  54. * Avoid nested stack-dumping if a panic occurs during oops processing
  55. */
  56. if (!test_taint(TAINT_DIE) && oops_in_progress <= 1)
  57. dump_stack();
  58. #endif
  59. /*
  60. * If kgdb is enabled, give it a chance to run before we stop all
  61. * the other CPUs or else we won't be able to debug processes left
  62. * running on them.
  63. */
  64. kgdb_panic(buf);
  65. /*
  66. * If we have crashed and we have a crash kernel loaded let it handle
  67. * everything else.
  68. * If we want to run this after calling panic_notifiers, pass
  69. * the "crash_kexec_post_notifiers" option to the kernel.
  70. *
  71. * Bypass the panic_cpu check and call __crash_kexec directly.
  72. */
  73. if (!_crash_kexec_post_notifiers) {
  74. printk_safe_flush_on_panic();
  75. __crash_kexec( NULL);
  76. /*
  77. * Note smp_send_stop is the usual smp shutdown function, which
  78. * unfortunately means it may not be hardened to work in a
  79. * panic situation.
  80. */
  81. smp_send_stop();
  82. } else {
  83. /*
  84. * If we want to do crash dump after notifier calls and
  85. * kmsg_dump, we will need architecture dependent extra
  86. * works in addition to stopping other CPUs.
  87. */
  88. crash_smp_send_stop();
  89. }
  90. /*
  91. * Run any panic handlers, including those that might need to
  92. * add information to the kmsg dump output.
  93. */
  94. atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
  95. /* Call flush even twice. It tries harder with a single online CPU */
  96. printk_safe_flush_on_panic();
  97. kmsg_dump(KMSG_DUMP_PANIC);
  98. /*
  99. * If you doubt kdump always works fine in any situation,
  100. * "crash_kexec_post_notifiers" offers you a chance to run
  101. * panic_notifiers and dumping kmsg before kdump.
  102. * Note: since some panic_notifiers can make crashed kernel
  103. * more unstable, it can increase risks of the kdump failure too.
  104. *
  105. * Bypass the panic_cpu check and call __crash_kexec directly.
  106. */
  107. if (_crash_kexec_post_notifiers)
  108. __crash_kexec( NULL);
  109. #ifdef CONFIG_VT
  110. unblank_screen();
  111. #endif
  112. console_unblank();
  113. /*
  114. * We may have ended up stopping the CPU holding the lock (in
  115. * smp_send_stop()) while still having some valuable data in the console
  116. * buffer. Try to acquire the lock then release it regardless of the
  117. * result. The release will also print the buffers out. Locks debug
  118. * should be disabled to avoid reporting bad unlock balance when
  119. * panic() is not being callled from OOPS.
  120. */
  121. debug_locks_off();
  122. console_flush_on_panic(CONSOLE_FLUSH_PENDING);
  123. panic_print_sys_info();
  124. if (!panic_blink)
  125. panic_blink = no_blink;
  126. if (panic_timeout > 0) {
  127. /*
  128. * Delay timeout seconds before rebooting the machine.
  129. * We can't use the "normal" timers since we just panicked.
  130. */
  131. pr_emerg( "Rebooting in %d seconds..\n", panic_timeout);
  132. for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {
  133. touch_nmi_watchdog();
  134. if (i >= i_next) {
  135. i += panic_blink(state ^= 1);
  136. i_next = i + 3600 / PANIC_BLINK_SPD;
  137. }
  138. mdelay(PANIC_TIMER_STEP);
  139. }
  140. }
  141. if (panic_timeout != 0) {
  142. /*
  143. * This will not be a clean reboot, with everything
  144. * shutting down. But if there is a chance of
  145. * rebooting the system it will be rebooted.
  146. */
  147. if (panic_reboot_mode != REBOOT_UNDEFINED)
  148. reboot_mode = panic_reboot_mode;
  149. emergency_restart();
  150. }
  151. #ifdef __sparc__
  152. {
  153. extern int stop_a_enabled;
  154. /* Make sure the user can actually press Stop-A (L1-A) */
  155. stop_a_enabled = 1;
  156. pr_emerg( "Press Stop-A (L1-A) from sun keyboard or send break\n"
  157. "twice on console to return to the boot prom\n");
  158. }
  159. #endif
  160. #if defined(CONFIG_S390)
  161. disabled_wait();
  162. #endif
  163. pr_emerg( "---[ end Kernel panic - not syncing: %s ]---\n", buf);
  164. /* Do not scroll important messages printed above */
  165. suppress_printk = 1;
  166. local_irq_enable();
  167. for (i = 0; ; i += PANIC_TIMER_STEP) {
  168. touch_softlockup_watchdog();
  169. if (i >= i_next) {
  170. i += panic_blink(state ^= 1);
  171. i_next = i + 3600 / PANIC_BLINK_SPD;
  172. }
  173. mdelay(PANIC_TIMER_STEP);
  174. }
  175. }
  176. EXPORT_SYMBOL(panic);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值