内核杂谈——浅谈kdump机理

杂谈

百分之百肯定的是,如果你的内核崩溃了,没有发生重启,那就说明重启内核是有问题的,谁来控制重启内核呢,答案是 kexec 工具。
kexec 工具被执行起来后,如果指定的新内核文件没有问题,就会默默的将这个内核文件保存到内核空间里,类似于open,然后系统发生死机后,就可以转生。

user kexec

和内核交互的工具,本质上是一个系统调用。kexec 做了那些事情?
1 获取 reserved 内存块。读取/proc/iomem中的Crash kernel字段的信息。这步失败就嗝屁了。
2 把指定的内核吃到自己定义的变量里。名字为 struct kexec_info info,包含代码段和加载地址,还有其他信息比如设备树,启动参数cmdline。指定的加载地址区间来自reserved 内存块。
3 设置 vmcore的生成开关 —— elfcorehdr。对于arm64来讲,具体表现在设备树中添加节点 linux,elfcorehdr;其他架构的话是在启动参数中添加 elfcorehdr= 。这些都会保存在kexec_info中

上面是内核起死回生并且生成vmcore的必要条件。

这里代码撸的比较头疼,结构体信息太多,和workqueue一个鬼样。但是里面的一些机理类似 memblock 玩法,还有一个机理就是elf文件各个段的解析。

kernel kexec

内核层会完成kexec_info接收,设置新内核实体。

kexec会陷入系统调用函数
SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
struct kexec_segment __user *, segments, unsigned long, flags)
主函数为 do_kexec_load。下面进入代码欣赏环节。以kexec -p举例,设置-p等于设置KEXEC_ON_CRASH

do_kexec_load:
	struct kimage **dest_image, *image;
	if (flags & KEXEC_ON_CRASH) {
		dest_image = &kexec_crash_image;	//新内核 kexec_crash_image
	} 

	if (flags & KEXEC_ON_CRASH) {
		kimage_free(xchg(&kexec_crash_image, NULL));	//清除新内核内容
	}
//将kexec_info读进来,存到image
	ret = kimage_alloc_init(&image, entry, nr_segments, segments, flags);
//将各个段存到指定的加载地址。使用kmap。本质上就是从加载地址获取一个page,转为地址,然后存到该地址
//如果预留内存不足,返回-ENOMEM
	for (i = 0; i < nr_segments; i++) {
		ret = kimage_load_segment(image, &image->segment[i]);
	}

	image = xchg(dest_image, image);	//到此,新内核 kexec_crash_image 加载完成。

各个段的存放地址是在reserved内存中

panic后会加载新内核
__crash_kexec:

	if (kexec_crash_image) {
			machine_kexec(kexec_crash_image);
	}

读取新内核信息,然后热重启。重启与架构有关。 arm64会执行 cpu_soft_restart,然后调用到汇编。

vmcore

至于vmcore的生成是initcall函数自动完成的。

static int __init vmcore_init(void)
{
	if (!(is_vmcore_usable()))
		return rc;
	rc = parse_crash_elf_headers();
	if (rc) {
		pr_warn("Kdump: vmcore not initialized\n");
		return rc;
	}
	elfcorehdr_free(elfcorehdr_addr);
	elfcorehdr_addr = ELFCORE_ADDR_ERR;
//创建/proc/vmcore
	proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
	if (proc_vmcore)
		proc_vmcore->size = vmcore_size;
	return 0;
}
fs_initcall(vmcore_init);

is_vmcore_usable 会检查 elfcorehdr, kexec执行的时候做了这件事。

结语

是不是和open差不多?是不是copy_from_user?就问像不像吧。

arm64 流程
启动A内核 ——> 执行 kexec 程序读取内核,并将各个段指定到reserved内存地址 ,打包成kexec_info——> 陷入系统调用,内核读取kexec_info,并保存B内核,并使能vmcore ——> 发生panic,内核启动B内核 ——> 生成vmcore

公众号:linux码头

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
kdump是一个在Linux内核崩溃时收集dump信息的工具。它的设计目标是在遇到内核崩溃时,能够提供完整的内核转储信息,以便开发人员进行分析和调试。 kdump的工作原理是在系统启动时,设置一个保护内存区域,用于在内核崩溃时存储dump信息。当系统出现崩溃时,kdump会触发一个内核崩溃的路径,将所有的内核状态信息存储在这个保护区域中。然后,kdump会加载一个独立的小内核,这个小内核只包含了最小的功能,仅仅用于将之前存储的内核状态信息写入磁盘。这样,即使主内核发生崩溃,kdump仍然能够将dump信息保存下来。 kdump所收集的dump信息包含了内核的堆栈、寄存器的状态、内核模块列表、内核代码和数据段等。这些信息对于开发人员分析和调试内核问题非常有帮助。无论是内核中的软件错误、硬件故障还是系统配置错误,都能够通过kdump的信息来定位和解决问题。 为了使用kdump,我们首先需要安装kexec工具,然后对系统进行一些配置,如设置内存保护区域的大小、crashkernel参数等。配置完成后,重新启动系统,当系统崩溃时,kdump就会自动工作。 总结来说,kdump是一个非常有用的Linux内核调试工具,能够在内核崩溃时提供完整的dump信息,为开发人员提供了方便的分析和调试手段。它能够帮助我们快速定位和解决各种内核问题,提高系统的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值