0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux pstore实现自动“抓捕”内核崩溃日志

Linux阅码场 来源:Linuxer 2020-06-28 09:50 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

作者简介

廖威雄,就职于珠海全志科技股份有限公司,负责Linux IO全栈研发、性能优化、开源社区开发交流、Linux 内核开源社区pstore/blk,mtdpstore模块的作者、大客户存储技术支持、全志首个UBI存储方案主导人、全志首个RTOS NFTL主导人

我设计的内核模块pstore/blk及其衍生的pstore/zone,mtdpstore终于在v5.8-rc1版本合入了torvalds/linux.git(见参考链接[1]),而且发现国内外对pstore的介绍都好少好少,干脆来一波科普

简介

pstore文件系统(是的,这是个文件系统)是Persistent Storage的缩写,最早在2010年由 Tony Luck 设计并合入Linux主分支,设计的初衷是在内核Panic/Oops时能自动转存内核日志(log_buf),在Panic重启后,把转存的日志以文件形式呈现到用户空间以分析内核崩溃问题。

这对分析那种小概率且没办法抓到现场的问题非常实用,尤其是现在智能互联网的设备逐渐普及的时候,远端的设备可以自己捕抓崩溃日志再通过网络传输到服务器,维护人员就可以根据收集来的日志定位和解决问题,然后通过OTA让设备升级迭代。

根据网上搜寻的资料,在pstore文件系统之前其实有不少类似的实现。

apanic
Android最早的panic信息记录的方案。在linux 2.6的安卓的内核中找到,却没有提交到社区,后来被放弃维护了。网上找不到放弃的原因,我自己猜测是因为其只适用于mtd nand,然而现在的Android基本用的都是emmc。apanic应该是Android Panic的缩写吧,可以实现在内核崩溃时,把日志转存到mtd nand。

ramoops
这里指的是最早的ramoops实现,在最新代码已经整合入pstore中,以pstore/ram的后端形式存在。ramoops可以把日志转存到重启不掉电的ram中。这里对ram有一点要求,即使重启ram的数据也不能丢失。

crashlog
这是openwrt提供的内核patch,并没有提交到内核社区。它也是基于ram,只能转存Panic/Oops的日志。

mtdoops
MTD子系统支持的功能,与pstore非常相似,只支持转存Panic/Oops日志,不能以文件呈现,需要用户自行解析整个MTD分区。(因为功能的相似,我实现了mtdpstore用于替代mtdoops)

kdump
如果说pstore是个轻量级的内核崩溃日志转存的方案,kdump则是一个重量级的问题分析工具。在崩溃时,由kdump产生一个用于捕抓当前信息的内核,该内核会收集内存所有信息到dump core文件中。在重启后,捕抓到的信息保存在特定的文件中。类似的还有netdump和diskdump。kdump的方案适用于服务器这种有大量资源的设备,功能也非常强大,但对嵌入式设备非常不友好。

pstore经过长期迭代,除了转存Panic/Oops的日志之外(dmesg前端),还支持pmsg、console和ftrace的前端,除了pstore/ram的后端之外,还有我设计的pstore/blk后端,除了支持转存到ram之外,还有block device和mtd device。

pstore的前端,是指转存的日志类型,pstore的后端,是指转存到什么类型的设备。

目前支持以下几个前端:

dmesg:主要是转存Panic/Oops时log_buf里面的内核日志

pmsg:提供给用户空间存储日志的入口,在Android里有看到被用于存储系统的日志。

console:终端日志

ftrace:function trace的信息

目前支持以下几种后端:

pstore/ram:Persistent Ram,重启不会丢数据的内存

pstore/blk:(v5.8以后的版本)所有可写的块设备,例如磁盘、U盘、emmc、NFTL nand等

mtd device:(v5.8以后的版本)mtd设备,例如 mtd nand。(mtd设备的支持依赖于 pstore/blk 后端,准确来说不是一种独立后端)

怎么用

就像把大象装入冰箱只需要打开冰箱,把大象放进去,关上冰箱门的3个步骤,使用pstore也只需要3个步骤:

使能pstore

挂载pstore文件系统

读取转存的日志文件

详细的说明可以看源码上的文档,本文只做基本功能的介绍。

Documentation/admin-guide/ramoops.rst

Documentation/admin-guide/pstore-blk.rst

使能

在menuconfig中选择内核pstore模块

$ make menuconfig |-> File systems |-> Miscellaneous filesystems |-> Persistent store support |-> Log kernel console messages # console 前端 |-> Log user space messages # pmsg 前端 |-> Persistent function tracer # ftrace 前端 |-> Log panic/oops to a RAM buffer # pstore/ram 后端 |-> Log panic/oops to a block device # pstore/blk 后端

上述两个后端2选1即可,前端就根据自己的需求选择,至于dmesg前端,默认使能没得选。如果希望用在mtd设备上,还需要选择mtdpstore模块:

$ make menuconfig |-> Device Drivers |-> Memory Technology Device (MTD) support |-> Log panic/oops to an MTD buffer based on pstore

选上就可以用了?虽然我非常想说“是的”,但事实却有点“骨感”。即使所有前端都使用默认配置,pstore/ram至少也需要知道可用的内存范围吧?pstore/blk至少也需要知道使用哪个块设备吧?

pstore/ram支持 模块参数(cmdline)、设备树、和Platform Data的3种配置方式,从代码来看,优先级关系是:模块参数 > Platform Data > 设备树。

pstore/blk支持Kconfig和 模块参数(cmdline)的两种配置方式,且模块参数比Kconfig有更高的优先级。

pstore/ram我接触也不多,直接介绍pstore/blk的使用方法。对新同学来说,请忽略一大堆乱七八糟的属性配置(使用默认值),只需要告诉pstore/blk后端使用哪个块设备即可。

在Kconfig中配置:

$ make menuconfig |-> File systems |-> Miscellaneous filesystems |-> Persistent store support |-> Log panic/oops to a block device # pstore/blk 后端|->() block device identifier #使用哪个块设备?

如果使用cmdline,可以这么写:

pstore_blk.blkdev=XXXX或者以模块加载:

$sudoinsmodpstore_blk.koblkdev=XXX

这里的块设备可以是代表整个磁盘的sda,也可以是代表某个分区的mmcblk0p4。虽然支持7种变体,但常用的还是两种:

/dev/: 例如,使用U盘的第2个分区,则是/dev/sdb2

::例如,mmc设备第6个分区,则是179:6

形式大概是这样:

$sudoinsmodpstore_blk.koblkdev=/dev/sdb2或者

$ cat /proc/cmdline.... pstore_blk.blkdev=179:6 ...

如果是mtd设备,可以直接指定mtd分区名或者编号,例如:

pstore_blk.blkdev=pstore#假设存在名为pstore的MTD分区

OK,对新同学来说,到这里配置就够了。可以从我的github(见参考链接[2])上看到我之前是怎么测试的。如果需要知道每个配置项的作用,还是看内核文档吧(ramoops.rst 或 pstore_blk.rst),或者在Kconfig中按h显示相关配置项的说明。

挂载

在使能且正确配置设备后,启动的时候应该会有这样的日志:

pstore_zone: registered pstore_blk as backend for kmsg(Oops,panic_write)pstore: Registered pstore_blk as persistent store backend

这代表pstore找到了设备且正常注册。接下来,我们还需要通过挂载的形式触发pstore从设备读取数据。常见的挂载是这样的:

mount-tpstorepstore/sys/fs/pstore挂载后,通过mount能看到类似这样的信息:

# mount...pstore on /sys/fs/pstore type pstore (rw,relatime)...

如果曾经触发过崩溃日志,在挂载点应该有类似这样的文件:

# ll /sys/fs/pstore...-r--r--r-- 1 root root 15521 Jan 1 00:06 dmesg-pstore_blk-0...

如果需要验证,咱们可以这样主动触发内核崩溃:

#echoc>/proc/sysrq-trigger

我是在U盘、SD卡、mmc、nand上验证的,maintainer Kees Cook 提供了另外一种基于loop的验证方法,实现用文件模拟块设备。当然这方法不适用于转存Panic日志,只能用于Oops或者其他前端:

# insmod pstore.ko compress=off# insmod pstore_zone.ko# truncate pstore-blk.raw --size 100M# losetup -f --show pstore-blk.raw/dev/loop0# insmod pstore_blk.ko blkdev=/dev/loop0 kmsg_size=16 console_size=64 best_effort=on

读取

经过上述的挂载后,可以在挂载点看到转存的日志文件。既然是文件,肯定支持文件的一系列操作,例如读取、删除。

root@TinaLinux:/sys/fs/pstore# head -n 10 dmesg-pstore_blk-1Oops: Total 2 timesOops#1 Part1<6>[ 2.743794] Bluetooth: RFCOMM socket layer initialized<6>[ 2.743813] Bluetooth: RFCOMM ver 1.11<6>[ 2.743822] 8021q: 802.1Q VLAN Support v1.8<3>[ 2.751766] reg-virt-consumer reg-virt-consumer.1: Failed to obtain supply 'drivevbus': -517<3>[ 2.752330] reg-virt-consumer reg-virt-consumer.1: Failed to obtain supply 'drivevbus': -517<5>[ 2.752742] ubi0: attaching mtd4<5>[ 2.890302] random: crng init done<5>[ 2.965927] ubi0: scanning is finished root@TinaLinux:/sys/fs/pstore# lldrwxr-x--- 2 root root 0 Jan 1 00:11 .drwxr-xr-x 5 root root 0 Jan 1 00:11 ..-r--r--r-- 1 root root 15521 Jan 1 00:06 dmesg-pstore_blk-0-r--r--r-- 1 root root 15128 Jan 1 00:11 dmesg-pstore_blk-1 root@TinaLinux:/sys/fs/pstore# rm dmesg-pstore_blk-1 root@TinaLinux:/sys/fs/pstore# lldrwxr-x--- 2 root root 0 Jan 1 00:13 .drwxr-xr-x 5 root root 0 Jan 1 00:11 ..-r--r--r-- 1 root root 15521 Jan 1 00:06 dmesg-pstore_blk-0

对dmesg前端的Panic/Oops日志,pstore会自动添加两行统计信息。例如:

Oops: Total 2 times # 表示触发了Oops,且是自系统安装后第一次启动以来第2次触发Oops。Oops#1 Part1 # 表示这是上一次运行期间第1次触发Oops的日志。

可以发现,第一行是累计总的触发次数,第二行是上一次启动触发的次数。

每个文件名的格式都是<前端名>-<后端名>-,例如dmesg-pstore_blk-1表示dmesg前端,pstore_blk后端以及是dmesg前端的第1个zone的日志。

当然,除了dmesg前端外,其他前端的名字大概是这样的:

# ll-r--r--r-- 1 root root 31 1月 15 11:53 console-pstore-blk-0-r--r--r-- 1 root root 3666 1月 15 11:53 demsg-pstore-blk-0-r--r--r-- 1 root root 65524 1月 15 11:53 ftrace-pstore-blk-0-r--r--r-- 1 root root 9 1月 15 11:53 pmsg-pstore-blk-0

除此之外,每个文件的时间戳表示崩溃触发的时间。上例中,由于系统并没有实现同步更新系统时间,所以时间戳不合理。

展望未来

正如我前文说的,pstore在物联网设备逐渐普及的现在,能发挥很大的作用,例如智能音箱和扫地机已经用起来了。

全功能支持

到目前为止,不管是块设备还是mtd设备,社区的代码都没能做到pstore的全部前端的支持。

设备 dmesg(Oops) dmesg(Panic) pmsg console ftrace
块设备 Y N Y Y Y
MTD设备 Y Y N N N
ram设备 Y Y Y Y Y

块设备如果需要记录Panic日志,需要提供一个在Panic时写块设备的接口。我在全志的mmc和nand驱动中实现了这样的接口,却因为种种原因不适合提交到社区。社区块驱动的适配寄希望于更多同学的努力了。

MTD设备很早前就有了panic_write()的定义,因此可以支持Panic日志转存。不支持其他前端,则是因为其擦写的物理特性。对pmsg,console,ftrace等这些不能页对齐写入的前端,还需要更多的适配工作。

迁移pstore/ram

在当前pstore的目录结构是这样的:

$ tree fs/pstorefs/pstore/├── blk.c # pstore/blk 后端的实现├── ftrace.c # ftrace 前端的实现├── inode.c # pstore 文件系统的注册与操作├── internal.h├── Kconfig├── Makefile├── platform.c # pstore 前后端功能的核心├── pmsg.c # pmsg 前端的实现├── ram.c # pstore/ram 后端的实现├── ram_core.c # pstore/ram 后端的实现└── zone.c # pstore/zone 实现存储空间的分配和管理

在我的补丁之前,只支持转存日志到ram,因此如果研读代码,我们会发现ram.c和ram_core.c实现了两部分功能:

dram空间分配与管理

dram的读写操作

我实现的blk.c支持了转存到块设备。但是后来发现不管pstore/ram还是pstore/blk,他们对于存储空间的分配和管理极度相似,我就提炼出了pstore/zone。于是乎,期望的代码层次应该是这样的:

pstore/ram要整合入pstore/zone已经与maintainer达成共识,但还需要更多同学一同努力做更多兼容,例如ecc的支持。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    4

    文章

    1482

    浏览量

    43144
  • Linux
    +关注

    关注

    88

    文章

    11860

    浏览量

    219837

原文标题:Linux pstore 实现自动“抓捕”内核崩溃日志

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    openKylin受邀参加Linux内核领域顶级技术峰会

    近日,Linux内核领域顶级技术峰会——LSF/MM/BPF 2026在克罗地亚萨格勒布举行。大会聚焦Linux内核存储、文件系统、内存管理以及BPF等关键技术方向,吸引了来自全球开源
    的头像 发表于 05-14 11:08 542次阅读

    Linux系统日志的分析方法和排查技巧

    日志是运维工程师排查问题的第一手资料。当服务器出现异常时,系统日志、应用日志、安全日志中往往隐藏着问题的答案。然而,很多工程师面对海量的日志
    的头像 发表于 05-14 10:44 425次阅读

    LX2160添加 pstore 功能来调试内核遇到的问题求解

    我尝试添加 pstore 功能来调试内核 启用以下内核配置: config_pstore=y config_pstore_console=y
    发表于 04-16 09:35

    如何理解Linux内核中的PCIe驱动

    我们习惯了用 Verilog 去死磕 PCIe 的底层协议状态机。但一旦越过硬件边界来到操作系统层面,Linux 内核是如何接管并驱动这些 PCI/PCIe 设备的呢?由于不同的 CPU 架构实现
    的头像 发表于 04-11 17:22 1405次阅读

    Linux内核无法恢复怎么处理?

    日志消息打印到 UART inresume_bl31会导致 Linux 内核无法恢复。 static void resume_bl31(struct s32g_ssram_mailbox
    发表于 03-16 06:02

    Linux内核驱动开发的技术核心精要

    ;initcall_debug用于启动优化;kgdb支持源码级调试;动态调试(dynamic debug)灵活开启日志内核移植新板时需实现时钟树、中断控制器、GPIO、早期串口等基础支撑,并正确编写设备树,最终使能
    发表于 03-10 13:56

    实战排障|RK平台启动卡死、SPL崩溃,两行日志直接定位DDR硬件死穴!

    在嵌入式Linux产品开发中,U-Boot SPL启动崩溃、主板不上电、启动卡死在初始化阶段是最让人头疼的硬故障之一。日志乱码、CPU异常复位、看不到完整启动流程,往往让软件工程师误以为是代码BUG,硬件工程师无从下手。
    的头像 发表于 02-24 15:22 1270次阅读
    实战排障|RK平台启动卡死、SPL<b class='flag-5'>崩溃</b>,两行<b class='flag-5'>日志</b>直接定位DDR硬件死穴!

    Linux内核bug狩猎指南:从栈跟踪到修复,官方文档教你搞定系统核心故障

    内核Linux 系统的 “心脏”—— 一旦它出 bug,小则功能异常,大则系统崩溃、死机。但内核 bug 往往藏在百万行代码中,想快速定位、修复绝非易事。
    的头像 发表于 02-06 16:59 3405次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>bug狩猎指南:从栈跟踪到修复,官方文档教你搞定系统核心故障

    拆解RK3568启动日志:Debian12+Linux6.1下的调试密码,初学者也能看懂

    在嵌入式开发中,启动日志(Boot Log) 是硬件调试、驱动开发、系统优化的“第一手资料”。尤其是基于瑞芯微 RK3568(四核 A55,主打边缘计算、物联网设备)的方案,搭配 Debian12 系统与 Linux6.1 内核
    的头像 发表于 02-06 16:52 3434次阅读
    拆解RK3568启动<b class='flag-5'>日志</b>:Debian12+<b class='flag-5'>Linux</b>6.1下的调试密码,初学者也能看懂

    RK3588 PCIe 压测:从崩溃到排障的全流程解析

    崩溃重启。今天我们就结合关键日志和代码,拆解问题根源,分享一套可复用的排障思路。     一、问题现场:从日志崩溃链条     我们先看两张关键
    的头像 发表于 02-06 07:11 668次阅读
    RK3588 PCIe 压测:从<b class='flag-5'>崩溃</b>到排障的全流程解析

    利用Last Log(Ramoops)排查系统问题:配置与实践指南

    Linux 内核的ramoops机制实现)可在系统异常时保存核心日志,为事后故障分析提供关键依据。本文将详细介绍其配置方法与问题排查实践,并通过具体案例演示实战流程。
    的头像 发表于 02-05 13:54 616次阅读
    利用Last Log(Ramoops)排查系统问题:配置与实践指南

    深入Linux内核:进程调度的核心逻辑与实现细节

    ,背后都离不开内核调度算法的精准操控。今天,我们就从优先级、调度算法、时间片分配到底层实现,全方位拆解Linux内核进程调度的核心逻辑。 一、进程调度的“身份标识”:优先级与分类 要理
    的头像 发表于 12-24 07:05 4711次阅读
    深入<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>:进程调度的核心逻辑与<b class='flag-5'>实现</b>细节

    Linux内核日志玩明白了吗?printk调试神器全解析

    前言:做Linux驱动开发或内核调试的朋友,一定对printk不陌生,但你真的会用它吗?为什么同样是调试RK3588内核,别人能精准捕捉关键错误,你却被海量日志淹没?今天就带大家吃透p
    的头像 发表于 12-19 08:32 1181次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>日志</b>玩明白了吗?printk调试神器全解析

    Linux内核printk日志级别全解析:从参数解读到实操配置

    一、开篇:一个命令引出的核心问题 在 Linux 终端执行 cat /proc/sys/kernel/printk,你可能会看到这样的输出: 这串数字不是随机的,而是内核日志系统的“核心配置开关
    的头像 发表于 11-20 15:54 2087次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>printk<b class='flag-5'>日志</b>级别全解析:从参数解读到实操配置

    华纳云服务器Linux系统日志集中化管理平台搭建

    在云计算时代,企业运维团队面临服务器数量激增带来的日志管理难题。本文详细解析如何基于Linux系统构建高效的云服务器日志集中化管理平台,涵盖日志采集、传输、存储和分析全流程,帮助运维人
    的头像 发表于 09-12 14:11 649次阅读