概念
ramoops 是 Linux 内核中的日志存储机制,将内核日志写入RAM 中,以便在系统崩溃或意外重启后能够保留日志信息供后续分析。
Panic捕获原理
在系统运行中,如果内核发生了panic,那么开发人员需要通过内核报错日志来进行定位问题。但是很多时候出现问题的时候没有接调试串口,而报错日志是在内存里面的,重启后就丢失了。所以需要一种方法,可以在系统发生crash时,将crash info保存于非易失存储器中。
内核使用kmsg_dump_register()
函数来注册捕获panic或者oops,如今内核已经有多种捕获panic的方式,最新的是pstore方式。
代码流程:
Kernel/panic.c
发生内核错误是会运行
void panic(const char *fmt, ...);
àkmsg_dump(KMSG_DUMP_PANIC);
à list_for_each_entry_rcu(dumper_list);
à dumper->dump(dumper,reason) ; ///运行kmsg_dump_register注册的回调函数
fs/pstore/ram.c
驱动和设备匹配后执行:
ramoops_probe();
à pstore_register
à pstore_register_kmsg
àkmsg_dump_register
- list_add_tail_rcu(dump_list) ; //插入链表中用于panic函数的回调,panic函数最后会执行pstore_dump();其链表插入方式为:dumper->dump = pstore_dump
à pstore_register_console
à pstore_register_pmsg
设备树配置
设备树属性有:
Unbufferd | 不是用缓冲 |
No-dump-oops | 不记录oops错误 |
Record-size | 记录错误的大小 |
Console-size | 终端dmesg的大小 |
Ftrace-size | 用于内核追踪框架的大小 |
Pmsg-size | 一般是内核打印的大小 |
Ecc-size | 记录错误的校验。 |
compatible | hi-target-ramoops |
由于ramoops是存储在非易失存储中,故设备树中需要给出一定的存储位置用于存放panic、ops、console的日志。大小最好大于16k
首先规划系统内存:
例如OMAP内存总共有256Mbit
248MiB | 0MiB | 8MiB |
运行Linux | 用于外部 | 运行rtos |
这样配置,只能通过运行linux的248MiB内存中拿出100K以上的。可使用linux自带的reserves预留内存:那么设备树配置为:
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
ramoops: ramoops@f600000 {
compatible = "hi-target-ramoops";
reg = <0xf600000 0x100000>;
record-size = <0x10000>;
console-size = <0x10000>;
};
};
或者:
246MiB | 2MiB | 8MiB |
运行Linux | 用于外部 | 运行rtos |
直接使用外部的内存;设备树配置
/{
ramoops: ramoops {
compatible = "hi-target-ramoops";
reg = <0xf600000 0x200000>;
record-size = <0x4000>;
console-size = <0x4000>;
};
}
内核配置
启动文件系统的pstore即可
CONFIG_PSTORE=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_RAM=y
CONFIG_REED_SOLOMON=y
CONFIG_REED_SOLOMON_ENC8=y
CONFIG_REED_SOLOMON_DEC8=y
编译
编译内核和设备树