首页 > 编程知识 正文

fatal python error,调试内核的常用方法是使用

时间:2023-05-04 22:52:39 阅读:156954 作者:620

linux kdump

Kdump是一种获取崩溃的Linux内核转储的方法,但要找到说明其使用方法和内部结构的文档可能很难。 本文研究kdump使用的基础知识,研究kdump/kexec内核实现的内部。

Kexec是从Linux内核引导到内核的引导加载程序,有助于从第一个内核的上下文引导第二个内核。 Kexec关闭第一个内核,绕过BIOS或固件阶段,然后跳到第二个内核。 因此,在没有BIOS阶段的情况下,重新启动会变快。

Kdump可以与kexec APP应用程序一起使用。 例如,如果在第一个内核崩溃时调用第二个内核,则第二个内核将用于复制第一个内核的内存转储,并且可以使用gdb或崩溃等工具分析转储。 找出恐慌的原因。 本文使用术语“第一内核”表示当前正在运行的内核,使用术语“第二内核”表示使用kexec表示正在运行的内核,并捕获在当前内核出现紧急情况时用于运行的内核)

kexec机制在内核和用户空间中具有组件。 内核几乎不向kexec的重启功能提供系统调用。 一个名为kexec-tools的用户空间工具使用这些调用并提供可执行文件以加载和引导第二个内核。 在某些情况下,您可能希望在kexec-tools上方添加包装器。 这有助于捕获和保存各种转储目标配置的转储。 为了避免将上游kexec-tools与特定于发行版的kexec-tools代码混淆,本文使用distro-kexec-tools名称。 我的示例使用Fedora Linux发行版。

Fedora kexec工具在DNFinstallkexec-toolsFedora计算机上安装fedora-kexec-tools。 您可以在安装fedora-kexec-tools后运行systemctl start kdump来启动kdump服务。 启动此服务时,将创建根文件系统(initramfs ),其中包含用于装载和存储目标vmcore的资源以及将vmcore复制/转储到目标的命令。 然后,该服务将内核和initramfs加载到崩溃内核区域中的适当位置,以便在内核崩溃时运行。

Fedora包装器包含两个用户配置文件:

/etc/kdump.conf指定配置参数,需要重建initramfs才能进行修复。 例如,如果将转储目标从本地磁盘更改为安装NFS的磁盘,则必须加载与NFS相关的内核模块才能捕获内核。/etc/sysconfig/kdump指定不需要更改initramfs的配置参数。 例如,如果只需要更改传递给捕获内核的命令行参数,则不需要重建initramfs。 如果在启动kdump服务后内核出现紧急情况,则会执行内核捕获,并从initramfs进一步执行vmcore保存进程,然后重新启动到稳定的内核。

编译kexec工具kexec-tools源代码时,将提供一个名为kexec的可执行文件。 您可以使用同一个可执行文件加载和运行第二个内核,也可以加载和运行捕获内核。 可以在内核发生紧急情况时执行。

加载第二个内核的常规命令:

# kexec-l kernel.img---initrd=init ramfs-image.imgreuse-cmdline-- reuse-command line与第一个内核的命令行相同- -使用--initrd传递initramfs。 -l表示kexec APP应用程序本身(kexec -e )正在加载可执行的第二个内核。 使用-l加载的内核无法在内核崩溃时执行。 要加载内核崩溃时可以运行的捕获内核,必须传递-p而不是-l。

加载内核的一般命令:

# kexec-p kernel.img---initrd=init ramfs-image.imgreuse-cmdlineechoc/pros/sysrq-trigger会导致内核崩溃有关kexec-tools提供的选项的详细信息,请参见man kexec。 在进入关注内部实现的下一部分之前,请阅读以下kexec_dump演示。

Kdump :端到端的流程图1显示了流程图。 在第一次内核启动期间,必须为捕获内核保留Crashkernel内存。 crashkernel=Y @ X可以在内核命令行上传递。 @X是可选的。 crashkernel=256M适用于大多数x86_64系统; 但是,为崩溃内核选择合适的内存容量取决于许多因素,包括内核大小和initramfs以及initramfs中包含的模块和APP运行时内存要求。 有关如何传递崩溃的内核参数的信息,请参阅内核参数文档。

您可以将内核和initramfs映像传递给kexec可执行文件,如本节中的常规命令“kexec-tools”所示。 捕获内核可以与第一个内核相同或不同。 通常保持原样。 Initramfs是可选的。例如,如果内核是用CONFIG_INITRAMFS_SOURCE编译的,则不需要内核。 它通常包含与第一个initramfs不同的捕获initramfs。 这是因为捕获会自动执行

initramfs中的vmcore副本会更好。 当执行kexec时 ,它还会加载elfcorehdr数据和炼狱可执行文件。 elfcorehdr具有有关系统RAM存储器组织的信息,炼狱是在捕获内核执行并验证第二阶段二进制文件/数据具有正确的SHA之前执行的二进制文件。 炼狱也可以设为可选。

当第一个内核崩溃时,它会执行最少的必要退出过程,如果存在则切换到炼狱。 炼狱验证加载的二进制文件的SHA256,如果正确,则将控制权传递给捕获内核。 捕获内核根据从elfcorehdr接收到的系统RAM信息创建vmcore。 因此,捕获内核启动后,您将在/ proc / vmcore中看到第一个内核的转储。 现在,根据您使用的initramfs,您可以分析转储,将其复制到任何磁盘,或者可以有自动复制,然后重新启动到稳定的内核。

内核系统调用

内核提供了两个系统调用,即kexec_load()和kexec_file_load() ,当执行kexec -l时可用于加载第二个内核。 它还为reboot()系统调用提供了一个额外的标志,可以使用kexec -e引导它进入第二个内核。

kexec_load() : kexec_load()系统调用会加载一个新内核,稍后可通过reboot()执行该内核。 其原型定义如下:

long kexec_load(unsigned long entry, unsigned long nr_segments,struct kexec_segment *segments, unsigned long flags);

用户空间需要传递用于不同组件(例如内核,initramfs等)的段。因此, kexec可执行文件有助于准备这些段。 kexec_segment的结构如下所示:

struct kexec_segment {void *buf;/* Buffer in user space */size_t bufsz;/* Buffer length in user space */void *mem;/* Physical address of kernel */size_t memsz;/* Physical address length */};

当使用LINUX_REBOOT_CMD_KEXEC调用reboot()时 ,它将引导到kexec_load()加载的内核中。 如果将标志KEXEC_ON_CRASH传递给kexec_load() ,则将不会通过reboot(LINUX_REBOOT_CMD_KEXEC)执行加载的内核。 而是在内核崩溃时执行。 必须将CONFIG_KEXEC定义为使用kexec,并且应为kdump定义CONFIG_CRASH_DUMP 。

kexec_file_load() :作为用户,您仅将两个参数(即内核和initramfs)传递给kexec可执行文件。 然后, kexec从sysfs或其他内核信息源读取数据并创建所有段。 因此, kexec_file_load()简化了用户空间,您仅在其中传递内核和initramfs的文件描述符。 所有段准备工作的其余部分都由内核本身完成。 应该启用CONFIG_KEXEC_FILE以使用此系统调用。 其原型如下:

long kexec_file_load(int kernel_fd, int initrd_fd, unsigned longcmdline_len, const char __user * cmdline_ptr, unsigned longflags);

请注意, kexec_file_load()也接受命令行,而kexec_load()不接受。 内核具有不同的体系结构特定的方式来接受命令行。 因此,在使用kexec_load()的情况下, kexec-tools会将命令行通过段之一(如dtb或ELF引导说明等) 传递 。

当前,仅x86和PowerPC支持kexec_file_load() 。

内核崩溃时会发生什么

当第一个内核崩溃时,在将控制权传递给炼狱或捕获内核之前,它会执行以下操作:

准备CPU寄存器(请参阅内核代码中的crash_setup_regs() ); 更新vmcoreinfo注释(请参阅crash_save_vmcoreinfo() ); 关闭非崩溃的CPU并保存准备好的寄存器(请参见machine_crash_shutdown()和crash_save_cpu() ); 您可能还需要在此处禁用中断控制器; 最后,它执行kexec重启(请参阅machine_kexec() ),该重启将kexec段加载/刷新到内存,并将控制权交给入口段的执行。 入口段可以是炼狱或下一个内核的起始地址。 ELF程序头

kdump中涉及的大多数转储核心都是ELF格式。 因此,了解ELF程序标头很重要,尤其是在您要查找vmcore准备问题时。 每个ELF文件都有一个程序头,该头是:

由系统加载程序读取, 描述了程序应如何加载到内存中, 可以使用Objdump -p elf_file查找程序头。

vmcore的ELF程序标头示例:

# objdump -p vmcorevmcore:file format elf64-littleaarch64Program Header:NOTE off 0x0000000000010000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**0 filesz0x00000000000013e8 memsz 0x00000000000013e8 flags ---LOAD off 0x0000000000020000 vaddr 0xffff000008080000 paddr 0x0000004000280000 align 2**0 filesz0x0000000001460000 memsz 0x0000000001460000 flags rwxLOAD off 0x0000000001480000 vaddr 0xffff800000200000 paddr 0x0000004000200000 align 2**0 filesz0x000000007fc00000 memsz 0x000000007fc00000 flags rwxLOAD off 0x0000000081080000 vaddr 0xffff8000ffe00000 paddr 0x00000040ffe00000 align 2**0 filesz0x00000002fa7a0000 memsz 0x00000002fa7a0000 flags rwxLOAD off 0x000000037b820000 vaddr 0xffff8003fa9e0000 paddr 0x00000043fa9e0000 align 2**0 filesz0x0000000004fc0000 memsz 0x0000000004fc0000 flags rwxLOAD off 0x00000003807e0000 vaddr 0xffff8003ff9b0000 paddr 0x00000043ff9b0000 align 2**0 filesz0x0000000000010000 memsz 0x0000000000010000 flags rwxLOAD off 0x00000003807f0000 vaddr 0xffff8003ff9f0000 paddr 0x00000043ff9f0000 align 2**0 filesz0x0000000000610000 memsz 0x0000000000610000 flags rwx

在此示例中,有一个注释部分,其余为加载部分。 注释部分包含有关CPU注释的信息,加载部分包含有关复制的系统RAM组件的信息。

Vmcore以elfcorehdr开头 ,其结构与ELF程序标头相同。 请参见图2中的elfcorehdr表示:

kexec-tools读取/ sys / devices / system / cpu / cpu%d / crash_notes并为CPU PT_NOTE准备标头。 同样,它读取/ sys / kernel / vmcoreinfo并为vmcoreinfo PT_NOTE准备头,并从/ proc / iomem读取系统RAM值并准备内存PT_LOAD头。 当捕获内核接收到elfcorehdr时 ,它将从标头中提到的地址追加数据并准备vmcore。

崩溃提示

崩溃注解是每个CPU的区域,用于在系统崩溃时存储CPU状态。 它具有有关当前PID和CPU寄存器的信息。

vmcoreinfo

此注释部分包含各种内核调试信息,例如结构大小,符号值,页面大小等。这些值由捕获内核解析并嵌入到/ proc / vmcore中 。 vmcoreinfo主要由makedumpfile应用程序使用。 Linux内核中的include / linux / kexec.h具有定义新vmcoreinfo的宏。 一些示例宏如下所示:

VMCOREINFO_PAGESIZE() VMCOREINFO_SYMBOL() VMCOREINFO_SIZE() VMCOREINFO_STRUCT_SIZE() makedumpfile

vmcore中的许多信息(例如空闲页面)都没有用。 Makedumpfile是一个排除不必要页面的应用程序,例如:

充满零的页面, 缓存没有私有标志的页面(非私有缓存); 缓存带有私有标志的页面(私有缓存); 用户过程数据页面; 免费页面。

另外,makedumpfile在复制时会压缩/ proc / vmcore数据。 它还可以从转储中删除敏感的符号信息; 但是,它首先需要内核的调试信息。 此调试信息来自VMLINUX或vmcoreinfo ,其输出可以是ELF格式或kdump压缩格式。

典型用法:

# makedumpfile -l --message-level 1 -d 31 /proc/vmcore makedumpfilecore

有关详细信息,请参见man makedumpfile 。

调试kdump问题

新的kdump用户可能遇到的问题:

Kexec -p kernel_image没有成功 检查是否分配了崩溃内存。 cat / sys / kernel / kexec_crash_size不应为零。 猫/ proc / iomem | grep“崩溃内核”应具有分配的范围。 如果未分配,则在命令行中传递适当的crashkernel =参数。 如果未显示任何内容,则在kexec命令中传递-d并与kexec-tools邮件列表共享调试输出。 从第一个内核发出最后一条消息后,控制台上看不到任何内容(例如“再见”) 检查kexec -l kernel_image后跟kexec -e是否有效。 可能缺少特定于体系结构或计算机的选项。 炼狱SHA验证可能失败。 如果您的体系结构不支持炼狱中的控制台,则很难调试。 可能第二个内核提前崩溃了。 将您的系统的Earlycon / earlyprintk选项传递到第二个内核命令行。 与kexec-tools邮件列表共享第一个和捕获内核的dmesg日志。 资源资源 fedora-kexec工具 仓库: git://pkgs.fedoraproject.org/kexec-tools 邮件列表: kexec@lists.fedoraproject.org 描述:Specs文件和脚本提供了用户友好的命令/服务,以便可以在不同的用户场景中自动执行kexec-tools 。 kexec工具 仓库:git://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git 邮件列表: kexec@lists.infradead.org 说明:使用内核系统调用并提供用户命令kexec 。 Linux内核 仓库: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 邮件列表: kexec@lists.infradead.org 说明:实现kexec_load() , kexec_file_load()和reboot()系统调用以及特定于体系结构的代码,例如machine_kexec()和machine_crash_shutdown()等。 Makedump文件 仓库: git://git.code.sf.net/p/makedumpfile/code 邮件列表: kexec@lists.infradead.org 说明:从转储文件中压缩和过滤不必要的组件。

2017年6月20日在LinuxCon ContainerCon CloudOpen中国上的Pratyush Anand的KDUMP:使用和内部知识讲座中了解更多信息。

翻译自: https://opensource.com/article/17/6/kdump-usage-and-internals

linux kdump

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。