linux系统挂掉问题的分析

摘要:
2.假设我们知道系统关闭时的PC值,并且我们还想知道系统中的哪个进程关闭。请注意,每个用户进程的虚拟地址空间可能不同,因此pid_Find PC值位于map中的共享库libtest_Disassemble.txt(建议使用objdump反汇编)中的下一步可以查看代码中与偏移量对应的位置。

玩linux系统,经常遇到的一件事就是做了某个操作之后系统会突然挂掉,这要怎么办?

1. 首先我们要看log,看看是否会留下一些蛛丝马迹,比如PC/LR是否有留下来。
PC是ARM的一个寄存器,即程序计数器,他记下的是当前程序执行的位置;
LR是link register,它保存的是当前函数的返回地址,
所以我们可以善用PC/LR来帮助我们查找问题的根源。

2. 假设我们知道系统挂掉时的PC值,同时我们要知道你的系统中挂掉的process是哪一个,
这样再使用ps aux | grep my_process获取这个process的pid。
获得了process的pid,我们可以使用cat /proc/pid/maps > ./pid_maps获取该procss的虚拟地址空间。
注意每一个用户process的虚拟地址空间都可能不一样,因为虚拟地址空间的关系,
在系统中每一个用户process都认为自己是系统中唯一的一个process。

3. 因为我们有了PC值,所以接下来在pid_maps中找到PC值位于哪一个shared library中,
也就是说系统挂掉的点是在哪个.so中挂掉。此时我们根据PC值结合这只挂掉的libtest.so
计算出在libtest.so中的偏移量。

4. readelf -a ./libtest.so | grep offset
或者nm ./libtest.so | grep offset
或者objdump -d libtest.so > libtest_disassemble.txt(建议使用objdump反汇编)
来查看offset对应的代码中的位置。

5. 结合源代码进行分析,找到系统挂掉的具体位置。

使用这种方法的缺点是:
1. 如果系统挂掉时已经破坏了线程栈,那利用PC值分析的意义不大;
2. 如果系统是挂在内核空间,那也无法确认问题点,除非能够恢复出用户空间的线程栈。

nm命令会列出symbol value(symbol offset)、symbol type以及symbol name。
我们常见的symbol type有"T"和"t",这两种类型的symbol都位于text section(即代码段),
其中symbol type为"T"的symbol对应的是extern类型的函数,为"t"的则对应的是static类型的函数。
因为symbol value和symbol name是对应的,所以我们可以根据PC确定offset后找到
相应的symbol name从而确定问题点。
nm libtest.so > nm_libtest.txt

readelf命令用来显示elf格式文件的信息,以本文讨论的问题范畴来讲,感兴趣的是symbols。
所以我们可以使用readelf -s libtest.so > readelf_libtest.txt将libtest.so中的symbol
dump出来,以便于我们排查问题。

objdump用来dump obj类型文件的信息,有了这条命令我们可以对编译好的obj文件进行反汇编,
这样可以去查看代码执行的流程。很多时候,对我们解决问题会非常有帮助。
objdump -d libtest.so > objdump_libtest.txt

为什么要计算PC对应在.so(shared library)中的偏移量?
shared library不同于静态库:静态库是在编译时即被集成到可执行文件中;
而动态库是在你的程序运行时才被加载到RAM中。
在被映射到虚拟地址空间之前,动态连接库中的各个符号之间的相对地址是确定的;
但是程序运行之前,无法确定其在虚拟地址空间中的位置,所以才需要计算偏移量。

在可执行程序中,仅仅有一个指向动态连接库的指针。/etc/ld.so.conf是动态连接库的配置文件,
在运行程序时当需要某个动态库时,ldconfig根据/etc/ld.so.conf中的配置选择加载特定的动态库到RAM中。

从以上描述,我们知道使用动态库的优点是:(1)可执行程序的代码量会变小;(2)动态库
独立于可执行程序,所以当我们要修改动态库时我们仅仅需要重新编译这个动态库而不需要
将整个可执行程序都重新编译一次;(3)另外可以在程序运行时去替换新的动态库,给调试
程序带来了方便。

正因为动态库的独立性,所以也决定了其一些缺点的存在:
(1)如果你的系统中缺少某个你需要的动态库,那只能在你运行时才会发现问题;
(2)如果你调用的动态库中缺少你需要的API,那也只能在运行程序时才能发现问题。
在之前写过的文章里面,有做过类似的试验,这里我们仍然可以做几个试验:
(1)将libtest.so所在的path从LD_LIBRARY_PATH中移除,再执行你的程序看一下:
sh#error while loading shared libraries:
(2)在系统总暂时性的将你的libtest.so删除,再执行你的程序看一下:
sh#error while loading shared libraries:
(3)将某个API从libtest.so中拿掉,再执行你的程序看一下:
sh#./test_main: symbol lookup error: ./libtest.so: undefined symbol:

如果是加载某个动态库出错,那么先用ldd命令(ldd实际上只是一个script)来查看
可执行文件需要用到哪些共享库,然后依次检查这些共享库是否都存在;
接下来检查共享库所在的path是否都有添加在LD_LIBRARY_PATH中。

如果是动态库中缺少某个API从而导致执行程序时失败,那首先要确认缺少的API是哪一个(如何确认?),
接下来使用nm/readelf或者是objdump来获取libtest.so中的symbol了,然后再确认需要的symbol是否
包含在libtest.so了。
nm libtest.so | grep your_api
readelf -s libtest.so | grep your_api
objdump -d libtest.so | grep your api
因为我们故意移除了your_api,所以在结果中应该搜索不到;
另外我们可以搜索其它的symbol看一下,应该会搜索到的,这样可以确认我们用的工具命令没有问题。

待解决问题:
可执行程序是如何调用动态库中提供的API?
为什么有时候找不到符号,是因为在编译代码时被stripped掉了吗?

免责声明:文章转载自《linux系统挂掉问题的分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇GC日志时间分析解决绝对定位div position: absolute 后面的<a> Link不能点击下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

mac上用teamviewer远程windows输入问题

问题: 在mac上用teamviewer远程windows时,碰到shift,=等按键无效的问题。 解决办法: 远程桌面连接服务器时,键盘不能正常打字。此时把windows自带的小键盘打开后,此时再用键盘就能正常输入。 打开小键盘的方法: 1、cmd+R打开命令行,输入:osk 2、开始-附件-轻松访问-屏幕键盘...

(翻译)Entity Framework技巧系列之五 Tip 16 – 19

提示16. 当前如何模拟.NET 4.0的ObjectSet<T> 背景: 当前要成为一名EF的高级用户,你确实需要熟悉EntitySet。例如,你需要理解EntitySet以便使用 AttachTo(…) 或创建EntityKey。 在大部分情况下,针对每个对象/clr类型只有一个可能的EntitySet。Tip 13正是利用这种想法来简化附...

CentOS7进程管理systemd详解

  概述: 系统启动过程中,当内核启动完成,后加载根文件系统,后就绪的一些用户空间的服务的管理工作,就交由init进行启动和管理,在CentOS6之前的init的管理方式都类似,相关的内容我们在之前的文章中也做出过介绍。在CentOS7上,init变成了systemd,其管理方式也发生了重大的变化,本章就跟大家欧一起探讨一些关于CentOS7上的sys...

如何在Ubuntu 20.04 / 18.04或更老版本中安装ifconfig

Ubuntu Linux是最流行的操作系统之一,因此,如果你正在使用它,并希望使用Ifconfig命令查看系统的Ip地址,那么有办法安装它。就像在Windows中的ipconfig一样,我们有ifconfig for Linux操作系统来获取和使用命令行查看所有可用的网络适配器的Ip地址。然而,默认情况下,它不会出现在你的Ubuntu系统中,这需要手动安装...

一台服务器能支撑多少个TCP连接

1. 困惑很多人的并发问题   在网络开发中,我发现有很多同学对一个基础问题始终是没有彻底搞明白。那就是一台服务器最大究竟能支持多少个网络连接?我想我有必要单独发一篇文章来好好说一下这个问题。   很多同学看到这个问题的第一反应是65535。原因是:"听说端口号最多有65535个,那长连接就最多保持65535个了"。是这样的吗?还有的人说:"应该受TCP连...

WPS修改批注部分的字体颜色?

今天遇到一个问题,就是复制文档的时候有几块红色字体想改成黑色,怎么也改不成功,通过修改字体颜色无效,通过百度找到了解决方法记录一下。 解决方法 审阅——显示标记——点击插入和删除(去掉前面的对钩即可) 可能是因为批注的问题吧 参考 为什么WPS改不了字体颜色?:https://www.zhihu.com/question/303687277 订阅...