阴沟翻船,马失前蹄,说明凡事皆有可能。自然,程序设计的再好,也会有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 系统 ...
随机推荐
-
python click module for command line interface
Click Module(一) ----xiaojikuaipao The following mat ...
-
sscanf格式化输出
char DesChar[20] = {0}; char* SouChar= "1cZCD23456abEFdedfB"; sscanf(SouChar,"%[^A-Z] ...
-
(七)DAC0832 数模转换芯片的应用 以及运算放大器的学习 01
DAC0832是8分辨率的D/A转换集成芯片.与微处理器完全兼容.这个DA芯片以其价格低廉.接口简单.转换控制容易等优点,在单片机应用系统中得到广泛的应用.D/A转换器由8位输入锁存器.8位DAC寄存 ...
-
Android仿iPhone晃动撤销输入功能(微信摇一摇功能)
重力传感器微信摇一摇SensorMannager自定义alertdialogSensorEventListener 很多程序中我们可能会输入长文本内容,比如短信,写便笺等,如果想一次性撤销所有的键入内 ...
-
Qt5-控件-QRadioButton-单选按钮-用于从多个选项中选取一个-单选神器
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QRadioButton> ...
-
ASP.NET事务存储过程
--修改存储过程 alter proc proc_get_student as select * from student; asp.net 的事务就是针对数据层来处理的呀! 没有数据处理不能使用事务 ...
-
db2迁移至oracle过程中的问题
(1)时间日期问题: db2中‘2013-07-17 00:02:55’ oracle中to_date('2013-07-17 00:02:55' , 'YYYY-MM-DD HH24:MI:SI ...
-
MySQL之B+树索引(转自掘金小册 MySQL是怎样运行的,版权归作者所有!)
每个索引都对应一棵B+树,B+树分为好多层,最下边一层是叶子节点,其余的是内节点.所有用户记录都存储在B+树的叶子节点,所有目录项记录都存储在内节点. InnoDB存储引擎会自动为主键(如果没有它会自 ...
-
Mysql的多种安装方法———rpm安装
下载地址 搜狐镜像:http://mirrors.sohu.com/mysql 官方网址:https://dev.mysql.com/downloads/mysql/ 一.rpm安装方式 从下载地址下 ...
-
jquery中的 deferred之 deferred对象 (一)
案例: var def=$.Deferred(); console.log(def);//答案见 图1 图1: deferred就是一个有这些方法的对象. 看源码分析: Deferred: funct ...