玩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系统挂掉问题的分析的更多相关文章

  1. Linux 系统负载查询及分析说明

    Linux 系统出现死机或卡顿时,可以参阅如下步骤进行整体排查: 检查服务器进程与服务否占用了过多内存,或者内存没有正常释放,导致出现内存溢出,系统宕机. 检查 /var/spool/cron 等系统 ...

  2. LInux系统木马植入排查分析 及 应用漏洞修复配置(隐藏bannner版本等)

    在日常繁琐的运维工作中,对linux服务器进行安全检查是一个非常重要的环节.今天,分享一下如何检查linux系统是否遭受了入侵? 一.是否入侵检查 1)检查系统日志 检查系统错误登陆日志,统计IP重试 ...

  3. Linux系统及应用问题分析排查工具

    linux 阿里技术协会 摘要: Linux服务器上经常遇到一些系统和应用上的问题,如何分析排查,需要利器,下面总结列表了一些常用工具.trace tool:最后也列举了最近hadoop社区在开发发展 ...

  4. Linux系统网络性能实例分析

    由于TCP/IP是使用最普遍的Internet协议,下面只集中讨论TCP/IP 栈和以太网(Ethernet).术语 LinuxTCP/IP栈和 Linux网络栈可互换使用,因为 TCP/IP栈是 L ...

  5. linux系统卡顿 性能分析

    systemtrap 是一个内核开发者要掌握的工具. linux performance analysis 系统瓶颈性能分析软件

  6. linux系统 web在线日志分析

    线上环境出现问题时,不能像本地环境一样,断点查找问题,只有根据日志分析来定位问题,当然有资深的经验也是可以的,哈哈. 最基本的就是cat命令,可以通过cat filename,来查看文件全部内容, & ...

  7. 《Linux内核分析》第三周 构建一个简单的Linux系统MenuOS

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK THREE ...

  8. Linux内核分析第三周学习总结:构造一个简单的Linux系统MenuOS

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.Linux内 ...

  9. 一次Linux系统被攻击的分析过程

    IT行业发展到现在,安全问题已经变得至关重要,从最近的“棱镜门”事件中,折射出了很多安全问题,信息安全问题已变得刻不容缓,而做为运维人员,就必须了解一些安全运维准则,同时,要保护自己所负责的业务,首先 ...

随机推荐

  1. 转: seajs手册与文档之 -- 模块标识

    目录 模块标识 相对标识 顶级标识 普通路径 文件后缀的提示 模块标识 模块标识是一个字符串,用来标识模块.在 require. require.async 等加载函数中,第一个参数都是模块标识.de ...

  2. Vim中如何全选并复制?

    全部删除:按esc后,然后dG全部复制:按esc后,然后ggyG 全选高亮显示:按esc后,然后ggvG(这个好像有点问题)或者ggVG正确 vim如何与剪贴板交互(将vim的内容复制出来) 习惯了在 ...

  3. Object 保存到文件中

    6月4日 Object 保存到文件中  Q. 你添加一个新类到你的项目当中且你希望可以保存这个类的一个实例对象到磁盘文件 并在需要时从磁盘文件读回到内存中  A. 方案  确保你的类遵循 NSCodi ...

  4. IIS express 7.5 配置和多网站执行

    iis express7.5 支持xp 以上的操作系统,能够解决xp.iis的问题. 首先先下载安装iisexpress7.5地址是id=1038">点击打开链接下载完毕点击安装就可以 ...

  5. 【OpenCV】OpenCV2.4.6 与Visiual Studio 2008,Python2.7.5配置和图像载入显示

    自从OpenCV2.2开始,OpenCV 库便分成几个模块并位于lib文件中,本节介绍从OpenCV2.4.6与VS2008 .Python2.7.5如何配置环境,如何外部文件载 入图像.在窗口中显示 ...

  6. 循环次数( M - 暴力求解、打表)

    循环次数 Description           我们知道,在编程中,我们时常需要考虑到时间复杂度,特别是对于循环的部分.例如,         如果代码中出现         for(i=1;i ...

  7. Python之路Day8

    摘要: Socket编程 异常处理 线程.进程 1.socket编程 1.1 socket 三次握手,注意阻塞的应用. 1.2 socketserver(2.x写作:SocketServer) 实现多 ...

  8. Cshap 使用http发起请求.

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 using System; using System.I ...

  9. Java字符串排序中文+数字

    编写日期: 2013年9月15日 另一中解法:点击查看 解决思路: 在Java中,排序需要复写的是 equals 方法 和 Comparable<T> 接口 的public int com ...

  10. 利用httpclient和多线程刷訪问量代码

    缘起于玩唱吧,由于唱吧好友少,訪问量低,又不想加什么亲友团之类的,主要是太麻烦了,于是我就琢磨唱吧的訪问机制,准备用java的httpclient库来进行刷訪问量,想到动态IP反复使用就想到了用多线程 ...