文章目录

  • 1.1 Kexec 和 Kdump
    • 1.1.1 Kexec 加载优点
    • 1.1.2 kdump 功能
    • 1.1.3 kdump原理
  • 1.2 Crash tool
    • 1.2.1 ramdump 机制
    • 1.2.2 Crash 路径设置
    • 1.2.3 Crash 常用命令
    • 1.2.4 bt 栈查看
  • 1.3 Kernel 常见宕机问题
    • 1.3.1 死锁问题
    • 1.3.2 OOPs
    • 1.3.3 BUG_ON和WARN_ON

1.1 Kexec 和 Kdump

Kexec 是一种可以从当前运行的内核引导进入另一内核的工具。可以在不执行任何硬件初始化的情况下加快系统重引导速度。还可以准备好系统,以便在系统崩溃的情况下引导进入另一内核。

1.1.1 Kexec 加载优点

使用 Kexec 可将运行中的内核替换为另一内核,而无需硬性重引导。该工具非常有用,原因如下:

  • 加快系统重引导速度;
  • 如果需要频繁重引导系统,Kexec 可以节省大量时间;
  • 避免不可靠的固件和硬件, 计算机硬件非常复杂,在系统启动期间可能会出现严重问题。并不总能立即更换掉不可靠的硬件。Kexec 可将内核引导到已初始化硬件的受控环境。这样,就可以最大程度地减少系统启动失败的风险;
  • 保存崩溃内核的转储, Kexec 可以保留物理内存的内容。在生产内核发生故障后,捕获内核(在预留内存范围内运行的附加内核)会保存有故障内核的状态。保存的映像可帮助后续分析;
  • 无需 bootlader 配置即可引导,当系统使用 Kexec 引导内核时,会跳过引导加载程序阶段。常规引导过程可能会由于引导加载程序配置中的错误而失败。使用 Kexec,就不需要考虑引导加载程序配置是否有效。

1.1.2 kdump 功能

kdump 是系统崩溃的时候,用来转储运行内存的一个工具。
系统一旦崩溃,内核就没法正常工作了,这个时候将由 kdump 提供一个用于捕获当前运行信息的内核,

该内核会将此时内存中的所有运行状态和数据信息收集到一个 dump core文件中以便之后分析崩溃原因。

一旦内存信息收集完成,可以让系统将自动重启

1.1.3 kdump原理

kexec 是 kdump机制的关键,包含两部分:
内核空间的系统调用kexec_load。负责在生产内核启动时将捕获内核加载到指定地址。

用户空间的工具kexec-tools。将捕获内核的地址传递给生产内核,从而在系统崩溃的时候找到捕获内核的地址并运行。

kdump是一种基于kexec的内核崩溃转储机制。当系统崩溃时,kdump使用kexec启动到第二个内核。第二个内核通常

叫做捕获内核,以很小内存启动以捕获转储镜像。第一个内核保留了内存的一部分给第二个内核启动使用。

由于kdump利用kexec启动捕获内核,绕过了 bootloader,所以第一个内核的内存得以保留。这是内存崩溃转储的本质。

1.2 Crash tool

当系统崩溃时,通过 kdump 可以获得当时的内存转储文件 vmcore,但是该如何分析 vmcore 呢?
crash 是一个用于分析内核转储文件的工具,一般和 kdump 搭配使用。
使用 crash 时,要求调试内核 vmlinux 在编译时带有 -g 选项,即带有调试信息。

如果没有指定 vmcore,则默认使用实时系统的内存来分析。 值得一提的是,crash也可以用来分析实时的系统内存,是一个很强大的调试工具。

Crash 工具 是在 GDB 的基础之上进一步开发的,所以 Crash 工具的很多命令在 gdb 上应该都是可以直接使用的,本篇文档主要介绍如何使用 Crash 来分析panic/hang 类型的一些 bug,这里需要注意的是有些 bug,如 hang,只能使用 etb 工具来查看最后各个 cpu 都在干什么。

1.2.1 ramdump 机制

在有些平台上,当 kernel 发生 panic 或者 hang 之后,会触发 SoC Watchdog Reset。有些公司的做法是:reboot 之前会在 PMIC 里面的某个寄存器里面写个值,来表明重启的原因,当再次重启的时候,会去读该寄存器,获取重启的原因。因为有时抓 ramdump 文件,需要获取重启的原因,比如 发生 Kernel Panic时,就需要获取 watch dog 重启的原因,如果检测到是 Kernel Panic 的话,就会去dump DDR 4G 的内容(因为 SoC resetDDR 内容不会丢失) 到 PC 或者 SD卡中。

1.2.2 Crash 路径设置

使用 Crash工具之间需要进行工具的路径设置,如下所示:

vim ~/.profile
export PATH=$PATH:..../devtools/crash_tools/:
source ~./profile

1.2.3 Crash 常用命令

bt -a
dis -lx function_name       //函数反汇编
dis -lr function_addr       //该地址反汇编
struct -o struct_name      //查看结构体各成员地址偏移情况
struct struct_name addr -x  //查看具体的值
crash> ps -C 0 -m //查看cpu0上面有哪些进程
CPU: 0
[0 00:00:00.024][IN]PID:3440 TASK:ffffffc042cf8000 CPU:0 COMMAND:"com.sina
[0 00:00:00.024][IN]PID:3771 TASK:ffffffc0b2915100 CPU:0 COMMAND:"ina.weib
crash> dfc_info                    //直接查看静态变量里面的值
crash> p/x 0xffffff80098dd000+3472 //地址的计算
crash> rd 0xffffffc0b2b65118
crash> vtop ffffff8009ea4000      //虚拟地址转为物理地址
crash> kmem -v
VMAP_AREA         VM_STRUCT         ADDRESS RANGE                   SIZE
ffffffc04862cd80 ffffffc03c875f00 ffffff8009e96000-ffffff8009ea0000 40960
ffffffc0b2b5a300 ffffffc0b2b5a280 ffffff8009ea4000-ffffff8009ea7000 12288
crash> vmap_area -x -p ffffffc0b2b5a300 //查看kernel虚拟地址的信息,-x:16进制
struct vmap_area {va_start = 0xffffff8009ea4000,  //上面虚拟地址所在进程的虚拟起始地址va_end = 0xffffff8009ea7000,    //上面虚拟地址所在进程的虚拟结束地址flags = 0x4, rb_node = {__rb_parent_color = 0xffffffc0ac64cd19, rb_right = 0xffffffc0acd7dd18, rb_left = 0xffffffc0b3517598}, list = {next = 0xffffffc0b2bb70b0, prev = 0xffffffc04862cdb0}, purge_list = {next = 0x0, prev = 0x0flags = 0x1, pages = 0x0, nr_pages = 0x0, phys_addr = 0xc0000000, caller = 0xffffff80083d3828 <devm_ioremap+88>}callback_head = {next = 0xffffff80088b811c <snd_soc_info_volsw>, func = 0xffffff80088b8bec <snd_soc_get_volsw>
}
/home/xiaoming/android9.1/kernel/linux/kernel/rcu/tree.c: 1717
0xffffff8008118f88 <rcu_advance_cbs+32>:   ldr     x2, [x29,#40]
0xffffff8008118f8c <rcu_advance_cbs+36>:   ldr     x3, [x2,#88]
0xffffff8008118f90 <rcu_advance_cbs+40>:   cbz     x3, 0xffffff8008118ff0\ <rcu_advance_cbs+136>
## dis -lx 0xffffff8008118ff0
crash> p sblog_str  //查看静态变量(或者全局变量)的值,即地址值
sblog_str = $13 = (struct sblog_struct *) 0xffffffc0b2b16418
crash> struct sblog_struct 0xffffffc0b2b16418 //查看结构体成员的值struct sblog_struct {dev = 0xffffffc0b2b6a400, clk = 0xffffffc0b2b58c00, res = {cipc_base_address = 0xffffff8009fc0100, comm_sb_addr = 0xffffff8013000000  //kernel虚拟地址无法读/*struct: read error: kernel virtual address: ffffff8013000000  /*type: "gdb_readmem_callback" struct: read error: kernel virtual /*address: ffffff8013000000  type:"gdb_readmem_callback"/*<Address 0xffffff8013000000 out of bounds>, comm_addr_offst = 0xc88000, comm_base_addr = 0x17000000 <Address 0x17000000 out of bounds>, ripc_size = 0x88, irq = 0x1b, .....}
}
crash> vtop 0xffffff8009fc0100 //物理地址转换为虚拟地址
VIRTUAL           PHYSICAL
ffffff8009fc0100  d40b0100     //所以对应的物理页帧

1.2.4 bt 栈查看

/* 1. 当前pc的值,也即函数 __stack_chk_fail 走到了这个位置 */
#1 [ffffffc0198bbb20] __stack_chk_fail at ffffff90080baf48  /* 存储的是上个函数的栈帧(FP)与返回地址(LR) */ ffffffc0198bbb20: ffffffc0198bbb40 ffffff9008b91914    ffffffc0198bbb30: 1ffffff803317774 ffffff9008b91680 /* 2. 函数i2cdev_ioctl_smbus当时走到了这里,/* 所以返回时需要走下一条指令:ffffff9008b91914#2 [ffffffc0198bbb40] i2cdev_ioctl_smbus at ffffff9008b91910

1.3 Kernel 常见宕机问题

1.3.1 死锁问题

常见的死锁有两种:
1)递归死锁:例如, 在中断等延迟操作中, 使用了锁,和外面的锁构成了递归死锁。一个锁导致的问题。
2)AB-BA死锁:多个锁因为处理不当而引发死锁,多个内合路径上的锁处理顺序不一致也会导致死锁。这里是多个锁导致的问题。

1.3.2 OOPs

当处理器在内核空间访问一个非法的指针时,因为虚拟地址到物理地址的映射关系没有建立,触发一个缺页异常,在缺页中断中因为该地址是非法的,内核无法为改地址建立映射关系,因此内核触发了一个Oops错误。

对于没有编译符号的二进制文件,可以使用 objdump 工具来 dump 出汇编代码,例如使用下面命令来 dump oops.o文件

arm-linux-gnueabi-objdump -d oops.o

内核提供了一个很好的脚本,可以用来帮忙快速定位问题,该脚本位于Linux 内核源代码目录的 scripts/decodecode ,首选将 log 保存到一个 txt 文件中:

./scripts/decodecode < oops.txt

1.3.3 BUG_ON和WARN_ON

对于 bug_on 当满足条件的时候,就会触发 BUG() 宏,它会调用 panic 函数主动让系统宕机,通常是一些 内核bug 才会触发 BUG_ON,在实际产品中使用该宏需要小心。
WARN_ON 不会触发 panic 但会答应函数调用栈信息,用来提示作用。

推荐阅读:
https://documentation.suse.com/zh-cn/sles/15-SP2/html/SLES-all/cha-tuning-kexec.html
https://www.cnblogs.com/muahao/p/9884175.html

【ARM Linux 系统稳定性分析入门及渐进 1 -- Crash 工具简介】相关推荐

  1. 目录 - 《ARM嵌入式Linux系统开发从入门到精通》 - 免费试读 - book.csdn.net

    第一部分 ARM Linux系统移植 第1章 嵌入式系统开发入门...... 2 1.1 嵌入式系统介绍..... 2 1.1.1 嵌入式系统概述..... 2 1.1.2 嵌入式系统组成..... ...

  2. Linux系统IO分析工具之iotop常用参数介绍

      Linux系统IO分析工具之iotop常用参数介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(iostat中的 ...

  3. linux下的arm仿真,使用QEMU仿真ARM Linux系统

    使用QEMU仿真ARM  Linux系统 使用方法,网上有很多文章可以参考: http://www.aurel32.net/info/debian_arm_qemu.php http://qemu-f ...

  4. 操作系统笔记——Linux系统实例分析、Windows系统实例分析

    文章目录 传送门 Linux进程管理 Linux进程组成 Linux进程链表 Linux进程控制 用户进程创建与撤销 0,1,2号进程 Linux进程切换 Linux进程调度 内核同步 Linux储存 ...

  5. Linux系统编程 / 分析开源软件Triggerhappy

    哈喽,我是老吴,继续记录我的学习心得 自制力太强导致低效专注 自制力很强的人的成功之道在于,在别人都放弃的情况下仍坚持不懈. 但是这反而会让他们难以关闭专注模式,导致无法进入解决难题所必要的发散模式. ...

  6. arm linux设置ip地址命令,ARM Linux系统修改动态IP为静态IP地址

    # Wired or wireless interfaces auto eth0 #iface eth0 inet dhcp #        pre-up /bin/grep -v -e " ...

  7. 状态观测器极点配置求解matlab,系统稳定性分析 、利用MATLAB 实现极点配置、设计状态观测器...

    订 装 实验报告 实验名称系统稳定性分析.利用MATLAB 实现极点配置.设计状态观测器 系专业班 姓名学号授课老师 预定时间实验时间实验台号 一.目的要求 掌握系统稳定性的概念.学会使用MATLAB ...

  8. Linux系统脚本分析之rc.sysinit

    Linux系统脚本分析之rc.sysinit #!/bin/bash # # /etc/rc.d/rc.sysinit - run once at boot time #  # # Rerun our ...

  9. linux系统下键盘按键的重新映射——xmodmap工具和xev工具

    虽然linux下小键盘还是不能用,但是找到一篇好文章 linux系统下键盘按键的重新映射--xmodmap工具和xev工具 文章目录 1. xev工具: 2. xmodmap工具 大家会不会有时候,感 ...

最新文章

  1. BP神经网络预测实例
  2. python爬虫为什么xpath路径正确却检索不到内容_中国知网爬虫
  3. 【转】文本格式导入物料凭证模板
  4. vue 中的el表达式_Vue中vue.filter()的使用方法介绍(过滤)
  5. builtins.ModuleNotFoundError: No module named ‘’scrapy.contrib‘’
  6. 线性代数导论2——矩阵消元
  7. 单表60亿记录等大数据场景的MySQL优化和运维之道 | 高可用架构
  8. Python爬虫编程实践 Task03
  9. Java英文单词翻译(API文档,IDE以及基本的java英文)
  10. 计算机毕设如何做?点进来,干货分享。
  11. SCI分区:JCR分区和中科院分区 的差别
  12. 打印机显示服务器脱机是什么原因,打印机显示“脱机”的原因和解决办法
  13. DOE实验设计操作手册
  14. 使用命令行把debian变成实时系统
  15. 人脸识别+表情识别系统
  16. FER 人脸表情识别
  17. 阿里云实时数仓搭建与组件选型
  18. meanShift算法介绍
  19. SAP License:利润中心
  20. 判定南京配眼镜哪家好的三步骤,轻松解决配镜烦恼

热门文章

  1. 【C++】基于固高驱动器的伺服电机项目调试
  2. ISL1208时钟芯片初始化
  3. 决策树(Decision Tree)算法 python简单实现
  4. 华清远见嵌入式c语言学习笔记
  5. 安徽师范大学计算机学院导师,安徽师范大学 数字计算机学院 耿焕同老师简介 联系方式 手机电话 邮箱...
  6. Tcl异常处理命令之try、throw
  7. 记录 uni-app 中对 data 的修改视图未更新的坑
  8. 哈工大形式语言与自动机2022期末试题
  9. ie调用java闪退_win7旗舰版系统位数不兼容导致IE浏览器频繁出现闪退怎么办
  10. March 4 2017 Week 10 Saturday