如何在重启后检测内核崩溃

3

我在一个嵌入式设备上遇到了意外的重新启动。通过 ioctl 调用,我目前能够检测到硬件看门狗问题。现在我想要检测内核崩溃是否是重新启动的原因。我找到了一些关于 crashkernel 和 crashdump 的文章,但我无法使其正常工作。而且我不想存储内核崩溃日志,只想知道是否发生了内核崩溃。

我的当前想法是在 mmc 上写入保留空间。我目前正在使用保留空间来处理双分发系统。这是一个好主意吗?在内核崩溃期间能否在 mmc 中进行写入?我不确定,但似乎我可以使用某种内核崩溃钩子来在此事件上运行例程。

是否有标准方法能够检查引导时是否发生了内核崩溃?


好的,当内核崩溃时,使用文件系统不是一个好主意。因此,我建议您避免访问eMMC,因为它包含您的rootfs。我不确定是否有可用的内核恐慌钩子。您可以编辑panic.c来切换一些LED(如果有的话),或将一些命令发送回UART,或在LCD上显示一些数据;任何事情,但请尽量避免在内核崩溃期间访问文件系统。 - Gaurav Pathak
我无法使用LED或UART。嵌入式设备不可物理访问。我目前正在尝试使用我的RTC的未使用寄存器来保存内核崩溃事件,以便在下次重启时能够检测到它。不确定这是否是处理我的用例的最佳实践。我正在使用atomic_notifier_chain_register API在内核崩溃时注册钩子。 - ArthurLambert
1
这听起来比在通知器中尝试操作文件系统要好得多。 - tofro
1
你需要搜索如何使用 pstoreramoops - 0andriy
2个回答

1
我能够检测和调试内核崩溃,这要归功于@0andriy的评论。如何在重新启动后检测内核崩溃
在内核defconfig中启用ramoops:
+CONFIG_PSTORE=y
+CONFIG_PSTORE_ZLIB_COMPRESS=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_RAM=y

在内核板初始化中添加代码来声明ramoops内存空间,你也可以使用设备树甚至在内核procline中使用参数。这是一个使用代码方法的示例,在我的用例中它位于arch/arm/mach-imx/mach-imx6ul.c文件中。
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -21,6 +21,24 @@
 #include "cpuidle.h"
 #include "hardware.h"

+#include <linux/pstore_ram.h>
+#include <linux/memblock.h>
+
+static struct ramoops_platform_data ramoops_data = {
+       .mem_address = 0xXXXXXXXX, // Depending of the hardware
+       .mem_size = 0x00005000, // 5 Mb
+       .record_size = 0x00002000, // 1 Mb
+       .dump_oops = 1,
+};
+
+static struct platform_device ramoops_dev = {
+       .name = "ramoops",
+       .dev = {
+               .platform_data = &ramoops_data,
+       },
+};
+
+
 static void __init imx6ul_enet_clk_init(void)
 {
        struct regmap *gpr;
@@ -170,6 +188,14 @@ static inline void imx6ul_enet_init(void)
 static void __init imx6ul_init_machine(void)
 {
        struct device *parent;
+       int ret;
+
+       ret = platform_device_register(&ramoops_dev);
+       if (ret) {
+               printk(KERN_ERR "unable to register platform device\n");
+               return;
+       }
+       memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size);

        parent = imx_soc_device_init();
        if (parent == NULL)

在启动时,我只需要检查ramoops的内容,以查看是否有可用的内核崩溃日志。我可以使用以下命令挂载ramoops内存空间:

mount -t pstore -o kmsg_bytes=1000 - /sys/fs/pstore

0

以下是Windows的处理方式:

  • 不再使用驱动程序
  • 使用BIOS例程(或类似低级别的东西)将数据写入磁盘
  • 将内核转储写入页面文件(唯一已知的连续且可写入而不会损坏任何内容的位置)
  • 在下一次启动时,检查页面文件是否包含崩溃转储签名

您可能可以将此概念应用于Linux,例如将数据写入交换分区,并在下一次启动时检查交换分区的内容。


不适用于Linux。Linux有自己的方法。 - 0andriy
@0andriy:当然有。有时你可以将一个操作系统的概念应用到另一个操作系统上。在Linux上,你不会写入页面文件,而是写入交换分区。 - Thomas Weller
这就是为什么它不能被视为问题的答案。请看我对OP的评论。 - 0andriy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接