linux panic流程

文章详细描述了当内核遇到panic时的处理机制,包括在SMP系统中的错误信息收集、内存转储、调试器接管、CPU停止以及系统重启或死循环等步骤。
摘要由CSDN通过智能技术生成

当内核走到panic时表明其已无法继续运行下去,因此需要执行一些系统挂死前的准备工作,其主要包含以下部分:

(1)在smp系统中,一个cpu正在处理panic时,可能另一个cpu也会触发panic。而该流程主要用于一些错误信息收集、内存转储等工作,并不需要也不支持并发操作。因此对于后续触发的cpu不需要执行该流程

(2)若正在使用kgdb对内核进行调试,则显然希望调试器能继续执行调试工作。故此时不会真正将系统挂死,而是将控制权转交给调试器

(3)若内核配置了kdump等内存转储功能,则在panic时将启动转储相关的流程

(4)在smp系统挂死之前,需要停止所有其它cpu的运行,以使系统真正地停下来

(5)最后,打印相关的系统信息后,使系统重启或进入死循环

 其相应的代码实现如下:

void panic(const char *fmt, ...)
{
	…
	this_cpu = raw_smp_processor_id();
	old_cpu  = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu);

	if (old_cpu != PANIC_CPU_INVALID && old_cpu != this_cpu)                       (1)
		panic_smp_self_stop();
	…
	pr_emerg("Kernel panic - not syncing: %s\n", buf);
	…
	kgdb_panic(buf);                                                               (2)

	if (!_crash_kexec_post_notifiers) {
		printk_safe_flush_on_panic();
		__crash_kexec(NULL);                                                   (3)

		smp_send_stop();                                                       (4)
	} else {
		crash_smp_send_stop();                                                 (5)
	}

	atomic_notifier_call_chain(&panic_notifier_list, 0, buf);                      (6)

	printk_safe_flush_on_panic();
	kmsg_dump(KMSG_DUMP_PANIC);                                                    (7)

	if (_crash_kexec_post_notifiers)
		__crash_kexec(NULL);                                                   (8)

	…
	panic_print_sys_info();                                                        (9)

	if (!panic_blink)
		panic_blink = no_blink;

	if (panic_timeout > 0) {
		pr_emerg("Rebooting in %d seconds..\n", 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);                                      (10)
		}
	}
	if (panic_timeout != 0) {
		if (panic_reboot_mode != REBOOT_UNDEFINED)
			reboot_mode = panic_reboot_mode;
		emergency_restart();                                                   (11)
	}
	…
	pr_emerg("---[ end Kernel panic - not syncing: %s ]---\n", buf);

	suppress_printk = 1;
	local_irq_enable();
	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);                                              (12)
	}
}

(1)若先前已经有cpu正在处理panic流程,则本cpu不再重复处理,只需将当前cpu停止

(2)打印panic原因信息

(3)若panic流程会执行内存转储,则所有系统相关信息都会被保存到转储文件中,因此就不需要调用后面的通知链,因此可直接调用转储操作。但是转储操作也不是100%保险,因此若不是对其绝对信任,则会设置_crash_kexec_post_notifiers,它会先执行通知链调用和log dump相关流程,再调用内核转储操作。

__crash_kexec函数会根据当前是否设置了转储内核确定是否实际执行转储操作,若执行转储则会通过kexec将系统切换到新的kdump内核,并且不再会返回。若不执行转储则继续执行后续流程

(4 - 5)停止当前cpu之外的其它cpu运行

(6)调用关心panic事件相关模块向其注册的通知

(7)dump内核log buffer中的log信息

(8)若设置了_crash_kexec_post_notifiers,则根据是否设置了kexec内核,确定是否执行内存转储操作

(9)若不执行内存转储,则打印系统相关信息

(10)若设置了panic_timeout超时值,则执行超时等待操作

(11)若设置了panic_timeout超时值,在超时等待完成后重启系统

(12)若未设置panic_timeout超时值,则将系统设置为死循环状态,使其挂死

### Linux Kernel Panic 原因分析 当操作系统遇到无法恢复的严重错误时,Linux 内核会触发 `Kernel Panic` 错误。这通常意味着内核检测到了可能导致数据丢失或其他不可逆损害的情况[^1]。 常见的引发因素包括但不限于: - **硬件故障**:内存条损坏、硬盘坏道等问题都可能引起此类异常。 - **驱动程序冲突**:新安装或更新后的设备驱动与现有环境存在兼容性问题。 - **文件系统损坏**:根分区或其他重要卷上的元数据受损也会造成崩溃。 - **配置不当**:SELinux策略设置过严或者其他安全模块限制了必要的操作权限。 对于特定情况下的 "not syncing" 提示,则表明日志同步机制未能正常工作,可能是由于底层存储子系统的致命缺陷所致[^2]。 ### 解决方案概述 针对上述提到的各种可能性,有几种通用的方法可以尝试来解决问题并防止其再次发生: #### 方法一:临时调整启动参数 通过GRUB引导加载器临时禁用某些强制执行的安全特性,允许机器能够成功启动至图形界面或命令行模式下进一步排查问题所在。具体做法是在 GRUB 菜单中找到对应内核版本那一项,追加 `enforcing=0` 参数后再继续启动流程。 这种方法虽然能快速绕过当前障碍恢复正常运行状态,但由于只是暂时规避而非根本修复,因此建议尽快采取更持久有效的措施。 #### 方法二:永久修改启动选项 为了使更改长期生效而不必每次都手动干预,可以在 `/etc/default/grub` 文件里添加相同的参数定义,之后重新生成 GRUB 配置文件以及刷新 MBR 记录以便改动立即起效。以下是具体的实现方式: ```bash sudo vi /etc/default/grub # 找到 GRUB_CMDLINE_LINUX 这一行,在双引号内部加入 enforcing=0 sudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg # 对于 UEFI 系统 sudo grub2-mkconfig -o /boot/grub2/grub.cfg # 对于 BIOS 系统 ``` 完成这些步骤后记得保存退出编辑器,并重启计算机验证效果如何。 另外还需要注意的是,如果是因为 SELinux 导致的问题,除了放宽控制级别外还可以考虑完全关闭该服务(仅限测试环境中),即把 `selinux=enforcing` 改成 `selinux=permissive` 或者直接设为 `disabled` 来观察现象变化。 最后提醒一点,以上所有操作均需谨慎行事以免带来不必要的风险;若有不确定之处最好先查阅官方文档获取最权威指导信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值