【问题标题】:How to detect a kernel panic after reboot重启后如何检测内核崩溃
【发布时间】:2018-05-24 19:12:58
【问题描述】:

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

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

没有标准方法可以检查启动时是否发生内核崩溃?

【问题讨论】:

  • 好吧,当Kenel 崩溃时使用文件系统不是一个好主意。因此,我建议您避免访问 eMMC,因为它会包含您的 rootfs。我不确定是否有可用的内核恐慌钩子。您可以编辑panic.c 来切换一些 LED(如果有的话)或将一些命令发送回 UART 或在 LCD 上显示一些数据;在内核崩溃期间尽量避免文件系统访问。
  • 我不能使用 led 或 uart。嵌入式设备在物理上是不可访问的。我目前正在尝试使用我的 rtc 的未使用寄存器来保存内核恐慌事件,以便能够在下次重新启动时检测到它。不确定这是处理我的用例的最佳实践。我正在使用 atomic_notifier_chain_register api 来注册内核恐慌的钩子。
  • 这听起来比尝试在通知程序中弄乱文件系统要好得多。
  • 你需要谷歌如何使用pstoreramoops

标签: linux-kernel embedded coredump panic


【解决方案1】:

以下是 Windows 的处理方式:

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

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

【讨论】:

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

感谢@0andriy How to detect a kernel panic after reboot 的评论,我能够检测和调试内核崩溃

在内核 defconfig 中启用 ramoops:

+CONFIG_PSTORE=y
+CONFIG_PSTORE_ZLIB_COMPRESS=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_RAM=y

在你的内核板初始化中添加代码来声明ramoops内存空间,你 还可以使用设备树,甚至可以在内核过程中使用参数 这是一个使用代码方法的例子,在我的用例中是 拱/臂/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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多