嵌入式系统coredump设计
阴沟翻船,马失前蹄,说明凡事皆有可能。自然,程序设计的再好,也会有crash的时候。开发期还还说,正式交付的系统crash自然更是难以承受的。无论何时,死一次就够了,得有方法查个水落石出。
几年前哥去广州的一家民企呆过些日子。刚到那,就碰上系统毫无线索的crash。咋办?哥想静下心来,花点时间做个工具去定位,但无奈硬件出生的领导天天赶着大家守在机房。唉,无知啊,天天守在机房,面对crash,哥想到的只有我儿子常常念的诗--来如春梦不多时,去如朝霞无觅处。嗯,crash,哥只能数数又crash了几次。
再后来,哥被请去了另外家公司,挂了个闲职,要求就一个,帮忙解决嵌入式系统开发碰到的,解决不了的问题。在那还是蛮幸福,因为哥那些日子确实需要时间,大把大把时间,来照顾家人。
这当中,就碰到三个最典型的问题:memory leak, system crash, system halt。内存泄漏以后再讲,今天只说crash,当然,halt跟crash的解决方法有很大重叠,明天有空就简单的说一说。
首先,简单定义下讨论对象:嵌入式操作系统,使用ucos,vxworks,nucleus等操作系统。Linux自带coredump功能,不在讨论范围。
接下来,普及下CPU的寄存器知识。以ARM为例,处理器存在几个不同的寄存器组,对应不同的模式:用户模式,中断模式,数据访问终止模式,未定义指令模式undef等。系统crash,除去硬件原因(比如电不足等),都是先触发异常:数据异常,取指异常,或者未定义异常。未定义异常一般来说是没有的,除非故意改掉指令的opcode,比如野指针,咱不谈它,那太难了!
有兴趣了解更多,可以读一读ARM的文档:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344f/Beiibjca.html
当Data aboat或是Prefetch abort出现后,CPU即切换到数据访问终止模式。我们要做的,就是抢在系统开始处理前,把用户寄存器信息保存下来。以及abort模式下LR寄存器内容。接下来,把控制权还给系统的正常流程。当然也不是绝对,哥碰到的系统,总是可以在异常里挂coredump处理函数。万一系统没给你留这个钩子,那就麻烦些,需要修改cpsr到用户模式,调用coredump处理函数;完成后,再返回abort模式,将处理权交还系统。当然,你不想交权也可以,coredump完了,就直接复位CPU。反正你该收集的信息都收集了,系统接下来的异常处理也没什么价值。
Coredump处理函数做的事,也很简单,首先确定当前运行的task和tcb。操作系统一定会提供这个全局变量,或是获取接口。然后,就是把堆栈信息保存起来。很多时候,堆栈会很大,很难保存所有数据。这时,就有几个策略:遍历堆栈,找出所有函数调用;提取栈顶的一段数据。其中原理等下再讲。
系统复位了,刚刚存的数据还在么?当然在,我们用SRAM来保存这些数据。CPU复位但不掉电的情况下,SRAM数据会完整的保留着。不过,系统要带SRAM。当然,没SRAM也可以,只不过做起来有点难度,需要flash驱动做些特别支持。数据需要先保存到内存中,然后在coredump处理函数中写入flash。写flash需要时间,因此要记得喂狗和写flash两不误;还有就是flash一般不能是文件系统,应该是直接的地址映射。flash的驱动必须配这种特俗的写操作。
然后,系统重新启动运行。这时候,我们先赶紧把刚才存在SRAM或是flash的数据复制出来,写入到coredump文件,免得夜长梦多。这个过程就很简单了!
接下来,解释几个技术问题。
怎么遍历堆栈,找到所有函数调用?
很简单。用readelf,objdump一类工具打开编译出来的软件包,你就能发现,函数地址总是在某个区间内。如果是动态加载的系统,则会提供代码段的区间范围。提前找到这个范围就好了,硬编码在你的程序里,且不需要精确,多一点没关系,毕竟相对于32位系统的地址空间来说,这段地址占的比例总是可以忽略不计,误抓取的信息也就非常有限。记得,宁可错杀一千一万!
为什么要保存栈顶数据?
一般来说,最后的一些列操作有更大的嫌疑。从分析角度来说,较远位置的错误,堆栈数据分析的难度非常大。其实,就经验来看,只要能找到函数调用的层次关系,再加上代码走读,基本上都能确定故障原因。堆栈数据分析,也就是不得已才做的,尤其是面对编译使用了优化选项的故障。
如何使用coredump文件?
coredump文件包含三个内容:寄存器信息,函数调用信息,堆栈数据。函数调用信息可以在线翻译,只要利用cshell里的符号表就可以直接查询那些地址,并翻译成可读的函数名。当然,最好的办法是离线处理。这里需要明确,编译时必须带-g参数用以产生addr2line需要的符号表内容。正式发布的软件包可以额外使用strip方法去掉符号表,但需要同时保存带符号表的原始编译软件包和发布软件包。利用addr2line对coredump保存的疑似地址检查,可以梳理出完整的系统调用层次。记得用Perl,或是Python等写个脚本来做这个!
很遗憾,哥找了半天,也没找到以前做的那段搞寄存器的汇编代码段,也没那段异常处理的函数代码,更也没找打coredump分析的perl脚本。早知道就该在给上家做这个的时候,偷偷复制一份供日后参考的。当然,也没什么,在弄清楚具体系统的工作原理后,相关实现估计只要一两个工作日来完成,只是没SRAM的方式,蛮复杂的,需要时间也多点,尤其测试会麻烦很多。
嵌入式系统coredump设计的更多相关文章
- 《嵌入式系统原理与接口技术》——嵌入式系统接口应用基础
本文为我负责编写的电子工业出版社出版的<嵌入式系统原理与接口技术>一书第七章部分,这里整理的仍然是修改稿,供需要的同学参考,本书为普通高等教育"十二五"规划教材,电子信 ...
- 嵌入式系统及应用课程设计——基于STM32的温湿度监测系统
大三上学期期末总结,嗯,没错上学期,写在新学期开始,hhh. 上学期学了一门嵌入式系统及应用的课程,期末的课程设计题目是基于STM32的温湿度监测系统. 记得刚开始做课程设计的时候,听说先设计画出原理 ...
- 多核片上系统(SoC)架构的嵌入式DSP软件设计
多核片上系统(SoC)架构的嵌入式DSP软件设计 Multicore a System-on-a-Chip (SoC) Architecture SoCs的软件开发涉及到基于最强大的计算模型在各种处理 ...
- 嵌入式Linux驱动学习之路(一)嵌入式系统的软硬件架构
硬件资料: 操作系统:(非虚拟机) zws@z-pc:~$ lsb_release -aNo LSB modules are available.Distributor ID: Ubuntu Desc ...
- 热烈庆祝华清远见2014嵌入式系统(Linux&Android)开发就业培训课程全面升级
近日,华清远见公开宣布:2014嵌入式系统 (Linux&Android)开发就业培训课程再次升级!据悉,华清远见如今已经持续10年,一直保持课程每年2次的更新的频率.华清远见的每 次课程更新 ...
- 嵌入式系统Linux内核开发工程师必须掌握的三十道题(转)
嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...
- Linux嵌入式系统与硬件平台的关系
一. Linux嵌入式系统 操作系统是一种在计算机上运行的软件,它的主要任务是管理计算机上的系统资源,为用户提供使用计算机及其外部设备的接口.它存在的目的是为了管理所有硬件资源,并且提供应用软件一个合 ...
- 嵌入式系统图形库GUI核心模块介绍
本文转载自:http://blog.csdn.net/xteda/article/details/6575278 (作者 冯青华 信庭嵌入式工作室(www.xteda.com)- CEO Blog:h ...
- 嵌入式系统 Boot Loader 技术内幕
转载:http://www.ibm.com/developerworks/cn/linux/l-btloader/index.html 1. 引言 在专用的嵌入式板子运行 GNU/Linux 系统 ...
随机推荐
- PCI Express(二) - Topology
原文出处:http://www.fpga4fun.com/PCI-Express2.html Point-to-point architecture At 2.5Gbps, the PCI Expre ...
- C语言的time.h解释python的time
clock_t clock(void),对比python的clock() 返回程序执行的时间,clock_t的实际类型是long #include<Windows.h> Sleep(); ...
- CentOS6.5 Openssl版本升级
CentOS6.5 Openssl 升级: 第一步:在openssl官网(https://www.openssl.org/)下载最新版 Ps:个人使用的是openssl-1.0.1u.tar.gz版 ...
- {POJ}{树状数组}
总结一下树状数组的题目: {POJ}{3928}{Ping Pong} 非常好的题目,要求寻找一个数组中满足A[i]<A[k]<A[j]的个数,其中i<k<j(或者相反).很巧 ...
- 循序渐进Python3(六) -- 初识内置变量、反射、递归
#python用下划线作为变量前缀和后缀指定特殊变量.稍后我们会发现, #对于程序来说,其中的有些变量是非常有用的,而其他的则是未知或者无用的. #我们总结一下Python中下划线的特殊用法 ...
- rotate the clock
A program test: You are given N round clocks. Every clock has M hands, and these hands can point to ...
- js基本常识了解
http://www.cnblogs.com/Yue0327/p/5441773.html
- E. Santa Claus and Tangerines 二分答案 + 记忆化搜索
http://codeforces.com/contest/752/problem/E 首先有一个东西就是,如果我要检测5,那么14我们认为它能产生2个5. 14 = 7 + 7.但是按照平均分的话, ...
- 使用 RecyclerView
使用 RecyclerView android RecyclerView tutorial 概述 与 ListView 的对比 RecyclerView 的组件 LayoutManager Recyc ...
- 简单的python服务器程序
一个接受telnet输入的服务器端小程序 #!/usr/local/bin/python3.5 #coding:utf-8 import socket host = '' port = 51423 s ...