linux reboot/panic

本文详细解析了嵌入式Linux系统中reboot和panic子系统的操作流程,包括reboot命令的用户空间和内核层面,以及panic子系统的触发机制和配置选项。还介绍了notifier机制在处理这些情况下的应用。

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

 转载:linux reboot/panic子系统 (jgsun.github.io)

1. Overview

作为一名嵌入式linux软件工程师,reboot命令是经常使用的命令,比如恢复板卡故障,板卡软件升级之后等。当敲了reboot命令之后,用户空间发生了什么操作?通过reboot系统调用到内核之后,内核reboot子系统又发生什么了操作,最终引导系统重启?板卡panic也会经常遇到,这绝对是嵌入式程序员的噩梦,但是内核panic子系统是如何工作的呢?了解内核reboot和panic子系统,有助于我们解决系统问题。

2. reboot流程图

image

对于嵌入式系统,reboot命令都是busybox集成,当敲入reboot命令之后,进入halt_main,向1号init进程发送SIGTERM信号;如果init-system采用busybox-init,则init进程的init_main接收到信号后给其他进程发送终止信号,最后调用C库函数reboot,reboot通过系统调用sys_reboot进入内核。 内核reboot子系统将根据系统调用参数将系统halt,poweroff或者restart;如果是restart将执行device驱动的shutdown函数,执行别的内核模块注册的reboot_notifier函数;然后执行syscore_shutdown,最后调用体系结构相关的函数machine_restart,这里以Marvell MIPS octeon为例,执行octeon_restart写cpu寄存器让系统重启。 如果init system是s6 init system,reboot命令用户空间流程如下,内核reboot流程和上图是一样的。 

image

3. panic流程图

在配置Linux Magic System Request(/drivers/tty/sysrq.c)的系统中,执行echo c > /proc/sysrq-trigger可以触发内核panic,可借此研究内核panic子系统。下面是marvell octeon平台的panic log:

~ # echo c > /proc/sysrq-trigger 
[ 8361.530756] sysrq: SysRq : Trigger a crash
[ 8361.534968] (c1 sh <518>) CPU 1 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffffc03f5364, ra == ffffffffc03f5354
[ 8361.549852] (c1 sh <518>) Oops[#1]:
[ 8361.554302] (c1 sh <518>) CPU: 1 PID: 518 Comm: sh Tainted: G O 4.9.79-Cavium-Octeon #113
[ 8361.564569] (c1 sh <518>) task: 800000005f0e1d00 task.stack: 800000005f168000
[ 8361.572662] $ 0 : 0000000000000000 0000000014009ce1 0000000000000001 ffffffffc19f0000
[ 8361.580731] $ 4 : ffffffffc08c8480 0000000000000001 800000005f0e2000 0000000000000000
[ 8361.588796] $ 8 : 00000000000001aa ffffffffc19fe308 0000000000004517 0000000000000001
[ 8361.596859] $12 : 0000000000000000 0000000000000007 0000000000000000 0000000000000006
[ 8361.604924] $16 : 0000000000000063 ffffffffc08c0000 ffffffffc08eea80 0000000000000007
[ 8361.612990] $20 : 0000000000000000 ffffffffc08ee760 ffffffffc08f0000 0000000000000020
[ 8361.621054] $24 : 0000000000000007 ffffffffc0400ae0                                  
[ 8361.629122] $28 : 800000005f168000 800000005f16bca0 000000001072156c ffffffffc03f5354
[ 8361.637188] (c1 sh <518>) Hi : 0000000000819446
[ 8361.642936] (c1 sh <518>) Lo : c8b4395810fc2de7
[ 8361.648694] (c1 sh <518>) epc : ffffffffc03f5364 sysrq_handle_crash+0x2c/0x40
[ 8361.656965] (c1 sh <518>) ra : ffffffffc03f5354 sysrq_handle_crash+0x1c/0x40
[ 8361.665231] Status: 14009ce3 KX SX UX KERNEL EXL IE 
[ 8361.670280] (c1 sh <518>) Cause : 0080000c (ExcCode 03)
[ 8361.676463] (c1 sh <518>) BadVA : 0000000000000000
[ 8361.682211] (c1 sh <518>) PrId : 000d9602 (Cavium Octeon III)
[ 8361.689000] Modules linked in: cpld_eps(O) uio_generic_driver(O) cpld_irq(O) cpld_spi(O) generic_access(O) generic_regmap(O) reborn_class(O)
[ 8361.701711] (c1 sh <518>) Process sh (pid: 518, threadinfo=800000005f168000, task=800000005f0e1d00, tls=0000000077eba620)
[ 8361.713625] Stack : 0000000000000000 ffffffffc03f559c 80000000027cdc68 800000006590b000
[ 8361.721689] fffffffffffffffb 00000000107242e0 0000000000000002 0000000000000004
[ 8361.729755] 0000000000000063 0000000000000030 0000000000000020 ffffffffc03f575c
[ 8361.737819] 0000000000000002 000000007fca2f90 0000000000000000 ffffffffc0230f94
[ 8361.745883] 0000000000000054 800000005f7b4c00 800000005f16be00 ffffffffc01c27e4
[ 8361.753948] 800000005f16be50 80000000027cdc00 0000000000000000 0000000000000054
[ 8361.762012] 0000000010069c28 ffffffffc0085068 0000000000030002 0000000000000000
[ 8361.770075] 0000000000000000 ffffffffc011fcc0 0000000100002301 800000005fb06000
[ 8361.778141] 8000000002763100 0000000000000002 800000005f7b4c00 ffffffffc01c2c04
[ 8361.786205] 800000005f16be00 ffffffffc01c018c 800000005f7b4c00 000000005f7b4c00
[ 8361.794271] ...
[ 8361.796743] (c1 sh <518>) Call Trace:
[ 8361.801364] (c1 sh <518>) [<ffffffffc03f5364>] sysrq_handle_crash+0x2c/0x40
[ 8361.809289] (c1 sh <518>) [<ffffffffc03f559c>] __handle_sysrq+0xc4/0x200
[ 8361.816952] (c1 sh <518>) [<ffffffffc03f575c>] write_sysrq_trigger+0x4c/0x68
[ 8361.824964] (c1 sh <518>) [<ffffffffc0230f94>] proc_reg_write+0x74/0xa8
[ 8361.832540] (c1 sh <518>) [<ffffffffc01c27e4>] __vfs_write+0x3c/0x128
[ 8361.839942] (c1 sh <518>) [<ffffffffc01c2c04>] vfs_write+0xb4/0x218
[ 8361.847170] (c1 sh <518>) [<ffffffffc01c4d28>] SyS_write+0x60/0xe0
[ 8361.854314] (c1 sh <518>) [<ffffffffc008111c>] syscall_common+0x18/0x44
[ 8361.861889] Code: 3c03c19f ac627470 0000000f <a0020000> dfbf0008 03e00008 67bd0010 00000000 03e00825 
[ 8361.871754] (c1 sh <518>) 
[ 8361.875444] (c1 sh <518>) ---[ end trace 67a7cc1a1dd2d4e5 ]---
[ 8361.882242] (c1 sh <518>) We will reset the spi-nor flash
[ 8361.888615] (c1 sh <518>) reset done!
[ 8361.893241] (c1 sh <518>) Kernel panic - not syncing: Fatal exception
[ 8361.900649] (c1 sh <518>) ---[ end Kernel panic - not syncing: Fatal exception

*** NMI Watchdog interrupt on Core 0x03 ***

panic流程图如下: 

image

sysrq的sysrq_handle_crash调用panic函数就触发了内核panic。 内核panic子系统将dump_stack,调用注册的notifier链表的回调函数,按配置打印系统信息(默认不打印,/proc/sys/kernel/panic_print)最后根据panic_timeout的值选择以那种方式触发系统重启。如果panic_timeout小于0,直接调用emergency_restart重启cpu;如果panic_timeout大于等于0,都将写watchdog导致watchdog超时重启,不同的是panic_timeout大于0,将delay一段时间重启。

3.1 panic 配置选项

新版内核提供/proc/sys/kernel/panic_print配置参数,可以让内核在panic的同时打印出系统信息:

#define PANIC_PRINT_TASK_INFO	0x00000001 //task信息
#define PANIC_PRINT_MEM_INFO	0x00000002 //内存信息
#define PANIC_PRINT_TIMER_INFO	0x00000004 //系统timer
#define PANIC_PRINT_LOCK_INFO	0x00000008 //lock信息
#define PANIC_PRINT_FTRACE_INFO	0x00000010 //打印ftrace
#define PANIC_PRINT_ALL_PRINTK_MSG	0x00000020//打印内核log_buf

比如设置panic_print为0x3F将打印出上述全部系统信息:

root@/proc/sys/kernel# echo 0x3F > panic_print
root@/proc/sys/kernel# cat panic_on_oops
1

4. reboot和panic的notifier机制

从上面reboot和panic的流程图可以看出,都将执行内核其他模块注册的notifier函数,可以利用这一机制,通过向注册reboot和panic子系统注册notifier函数,实现在rboot和panic过程中执行特定的任务:比如reboot的时候dump外设寄存器,重启外接设备,保护现场,置内存为自刷新模式,设置是warm还是poweron重启等;panic的时候记录系统panic次数,dump系统信息等。

5. 结束语

reboot看似简单,但是其实现却很复杂。内核遍历执行各个设备的shutdown方法;遍历执行notifier,systern core shutdown回调函数;最后调用arch相关的mechine_restart复位cpu。我们更多的是关注板卡的启动过程,很少关注reboot,只有出了reboot相关的问题后,才会去了解。理解整个reboot的流程,可以有助于我们定位问题;也可以帮助我们面对新feature,提出新的解决方案。以前遇到一个板卡reboot卡死的问题,经过调查发现是qspi flash没有复位造成的,最后通过在flash设备驱动中的shutdown函数中和panic函数中复位flash解决了这个问题。

### 关于内核崩溃(Kernel Panic)的原因 Kernel PanicLinux 操作系统中的一种紧急错误情况,当操作系统遇到无法正常处理的问题时,内核会决定这种“恐慌”状况,以保护系统不受进一步破坏[^1]。具体来说,可能导致 Kernel Panic 的原因有很多: - **硬件故障**:内存条损坏、硬盘坏道等问题都可能引发此现象。 - **驱动程序冲突或缺失**:新安装的设备未能找到合适的驱动支持;或是不同版本间的兼容性问题。 - **文件系统损坏**:根分区或其他重要挂载点的数据结构遭到破坏。 - **不当的操作行为**:如误操作删除了关键性的系统文件。 ### 解决方案 对于 Ubuntu 或其他基于 Linux 发行版上发生的 Kernel Panic 问题,可以尝试如下几种方式来解决问题: #### 方法一:临时调整 GRUB 启动参数 在系统启动过程中,可以通过编辑 GRUB 菜单项中的内核加载选项来进行调试。例如,在选定的内核命令行后面追加 `enforcing=0` 参数,这将暂时禁用 SELinux 安全策略强制模式,从而绕过某些由安全设置引起的启动障碍[^2]。 ```bash # 进入GRUB编辑界面后修改后的命令行应类似于下面这样: kernel /vmlinuz-version ro root=/dev/mapper/ubuntu--vg-root resume=/dev/mapper/ubuntu--vg-swap_1 splash quiet enforcing=0 ``` 这种方法的优点是可以快速验证是否为特定的安全配置所引起的问题,但缺点在于每次重启都需要重复相同的手动干预过程。 #### 方法二:永久修正 GRUB 配置文件 如果确认问题是由于某个固定的配置所致,则可以在 `/etc/default/grub` 文件里做出相应的更改,并通过更新 grub 来使这些改变生效。比如添加上述提到的 `enforcing=0` 到默认的 GRUB_CMDLINE_LINUX_DEFAULT 变量中去。 ```bash sudo nano /etc/default/grub # 修改GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" 行为 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash enforcing=0" sudo update-grub reboot ``` 完成以上步骤之后重新启动计算机,理论上应该能够恢复正常工作状态而不再显示 Kernel Panic 错误信息。 #### 方法三:修复受损的文件系统 如果是由于文件系统的损伤而导致的 Kernel Panic ,那么应当考虑使用 Live CD/USB 对磁盘进行检查并尝试恢复数据完整性。常见的工具包括但不限于 fsck (File System Consistency Check),它可以帮助扫描和修理大多数类型的本地文件系统。 ```bash sudo fsck /dev/sdXn # 替换sdXn为你实际使用的设备名称 ``` 此外还有专门针对 ext4, btrfs 等不同类型文件系统的专用维护工具可供选用。 #### 方法四:回滚最近一次变更 回顾近期所做的任何软件包升级活动或者是重要的系统级改动,特别是那些涉及到核心组件的部分。如果有条件的话,试着撤销这些变动——卸载最新安装的应用程序、降级至稳定版本的核心库等措施往往能有效缓解甚至彻底消除 Kernel Panic 所带来的困扰。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值