crash、kdump工具学习
kdump文档
- https://www.kernel.org/doc/Documentation/kdump/
- https://www.kernel.org/doc/html/latest/admin-guide/kdump/kdump.html
- Linux Kdump 机制详解
- 如何在Ubuntu18.04下安装和配置kdump
- linux kexec 介绍
- ubuntu 16.04 安装配置kdump
- CHAPTER 48. INSTALLING AND CONFIGURING KDUMP
- centos中vmcore的生成过程窥探以及优化
- makedumpfile
- kexec可执行程序的源码:https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
制作initrd.img
https://blog.csdn.net/qq_26884501/article/details/112311201
find . | cpio --quiet -H newc -o | gzip -9 -n > /data/boot/initrd.img
调试运行中的linux
crash vmlinux
或者
crash /dev/mem vmlinux
或者
crash /proc/kcore vmlinux
触发
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
crash命令学习
- 主页:https://crash-utility.github.io/
- 仓库:https://github.com/crash-utility/crash
- 帮助: https://crash-utility.github.io/help.html
- 白皮书:crash whitepaper
- 扩展模块:crash extension modules
- crash trace扩展:https://github.com/fujitsu/crash-trace
使用案例:
- Extracting kernel stack function arguments from Linux x86-64 kernel crash dumps
- crash实战:手把手教你使用crash分析内核dump
这里是基于8.0版本的crash编译的:
常用到的一些命令
- 根据percpu的偏移量获取它的虚拟地址
ptov <偏移量>:0,2,4-6
然后就可以使用rd
获取percpu变量在指定cpu上的值了。
系统宕机分析
熟练使用crash工具,对于分析系统异常宕机非常有帮助.当使用crash工具大致定位代码位置后,可以看一下跟新版的内核这块的有没有代码差异,如果有的话,可以用git blame
等命令查看一部分的提交记录,可能社区已经有修复同一个问题的patch了。
系统宕机的原因大致有如下几种:
- 访问了非法内存: 如果开启了Kasan的话,当遇到内存OOB以及UAF等问题时,也会宕机
- 死锁导致进程处于不可中断状态的时间过长,此时如果配置了
/proc/sys/kernel/hung_task_panic
为1,那么系统会panic - 在关闭了内核抢占的情况下,如果开启了softlockup宕机,那么当进程长时间运行在内核空间的话,也会导致宕机
非法内存访问
结合发生异常的调用栈、异常时的cpu寄存器上下文信息、源码以及反汇编来分析。
死锁
- 可以通过
foreach UN bt -sx
来遍历系统中所有处于D
状态的进程,并将每个D状态的进程的调用栈打印出来 - 对于锁或者信号量的分析:
-
如果是互斥锁,要找到当前谁持有这个锁以及哪些进程正阻塞在这个锁上比较容易。mutex.owner成员会记录当前正持有这把锁的进程的task_struct,由于地址对齐的原因,task_struct指针的低3位是空闲的,所以mutex会利用低3位来做一些其他工作。所以需要将owner的低3位屏蔽掉就可以获得谁持有这个互斥锁。
bit 宏 含义 0 MUTEX_FLAG_WAITERS 表示锁的等待队列是否位空,即此时是否已经有进程阻塞在这个锁上了 1 MUTEX_FLAG_HANDOFF 在释放互斥锁的时候,需要将锁的owner赋值为等待队列中的第一个进程 2 MUTEX_FLAG_PICKUP 获取被阻塞的进程:
list -O mutex.wait_list -o mutex_waiter.list -s mutex_waiter.task -h <mutex结构的虚地址>
-
对于读写信号量又可以分为普通的读写信号量,以及percpu的读写信号量,比较麻烦一些。
- 如果是普通的读写信号量:
- 获取写者:
- 获取读者:可以使用
search <锁地址>
在进程的内核栈里搜索,然后逐个分析。 - 获取被阻塞的进程:
- 如果是percpu读写信号量
- 获取写着:
- 获取读者:可以使用
search <锁地址>
在进程的内核栈里搜索,然后逐个分析。 - 获取被阻塞的进程:
- 如果是普通的读写信号量:
-
对于读写锁
-
进程相关
获取某个进程在cpu上运行了多长时间:
本文来自博客园,作者:摩斯电码,未经同意,禁止转载