软件问题的分析与解决
嵌入式软件由于调试手段的限制、部署场景的多样化、软硬件问题混合在一起、外部环境因素的影响等因素,导致软件经常会遇到一些非常难以解决的问题。
3.1 解题思想
熟悉软件的业务流程:从业务的角度发现问题、复现问题并解决问题。
熟悉软件的总体架构:软件架构是解决难题问题的基本框架,基于软件架构解决问题不会陷入到局部细节,导致修复一个问题的同时产生新的问题,不会犯原则性、方向性错误。
熟悉软件代码的实现:熟悉代码的细节,能够更好、更快的在蛛丝马迹中找到证据和突破点,甚至在问题还没有收敛前,提供一种收敛的方向,引领问题的解决,对代码的熟悉程度直接关系到解决问题的速度。
3.2 调试手段和信息不足相关问题
3.2.1 现场偶发性、难复现性引发的问题
一些偶发性现象级问题,甚至导致系统偶发性的重启,无法复现,设备重启之后,故障消失后,再也很难复现。
1、分析日志文件
从log中寻找异常提示,是应对不可重复性、偶发性故障最基本的手段。在系统某处发生异常时,一定会在log中留下蛛丝马迹,可以请客户协助提供串口日志,在log文件中查找问题。或者设备自己内部记录log,但嵌入式设备由于存储空间的限制,可能先前过于久远的信息,就会被新的信息被覆盖,针对这种情况,就需要定期清除无效日志。有些异常会导致系统重启,而重启之后,就会导致异常信息被正常重启的信息覆盖,这就需要系统能够支持log的备份。不管怎么样,log为定位现场问题提供了最基本的、最主要的信息来源。一个完善的log机制,对于定位现场问题非常有帮助。如果不满足,可能首要任务是先完善日志功能。
2、回退软件版本,紧急消除现场问题
有些现场问题,虽然偶发事件,但发生后影响严重,客户无法接受。针对这种情况,在解决问题之前,可以先把软件降级,降级到相对稳定,没有严重故障的版本。
3、比较相邻版本之间的代码改动
如果不容易复现的故障,确认在升级了某个软件版本之后才出现的,而其他现场条件都没有变化,且分析log也无法发现异常点。此时,一种高效的解决此问题的方法,就是比较两个版本之间的代码的改动。
代码改动比较少,分析代码比较容易;如果代码改动比较多,就需要根据用户描述的现象,结合前后代码的改动模块,初步分析最可能是哪个模块引起的,这种往往需要对系统架构较深刻的理解。在众多修改模块中,分析最有可能关联的代码模块的改动,然后逐一排查 。分析代码的改动与出现的现象之间可能的关联关系,对开发人员个人的技术素养和方法论有较高的要求 。比较相邻版本之间的代码改动,针对某些棘手的现场问题,有时候确实是一个非常有效的手段。
4、问题复现
虽然常规来说现场很难复现,但可以人为的修改软件、构建或增加模拟数据,人为创造或触发条件,增加故障复现的几率。在设计触发条件时,需要围绕用户描述的现场故障现象来设计触发条件,观察是否能否复现,且表现一致。
5、分析代码
根据用户描述的现象,硬分析代码,是一种通用的方法,放之四海皆准的方法,熟悉自身代码的逻辑关系是基本功,但解决问题的效率就比较难把握了。
6、增加 log 更新版本继续测
如果常规的log无法展现故障的异常,就需要在猜测有可能的部分增加日志,在现场复测。但这种日志添加的位置是否合理,决定了问题再次出现时是否能定位问题的准确性。这种方法在工程实践中,实施难度大,需要客户多次配合。
3.2.2 现象与真正的原因不在一起的问题
大多时候解决软件故障,是可以做到头痛医头,脚痛医脚。有些时候,头痛的原因并不在“头”,而在“脚”。这就需要知道“头痛” 与 “脚” 的某种关联关系。
解决这样的问题,对技术人员的综合技能的要求非常高,因为这个问题,不再是局部问题,而是发散到调查该问题的技术人员不熟悉的其他的软件组件领域。即使对于熟悉整个系统的人而言,也是一个难点,因为问题的现象与根源之间的路径是发散的,没有一个确切的路径。
首先,必须以故障的表面现象作为锚点,作为出发点。为后续进一步的调查立一个基点。根据现象找到出问题的代码,根据代码和log分析代码的表面原因。如果确实是本处代码的问题,直接在此解决即可。即头痛医头,脚痛医脚。
很多情形下,真正的原因不在显示异常的地方,比如收到了异常的事件、或参数不合理、或自身状态机的问题等。这时候就需要追溯,为什么会有这样的事件或消息?有时候,由于复杂系统的程序员没有系统的视角,常以为消除了故障表面现象就是解决了问题。很多时候站在系统的视角,可以从多个层面加以解决,消除异常事情,可以从规则过滤模块解决,也可从前置模块或后续模块解决。具体在哪儿解决最合理,这就需要有系统和结构的视角。当然,也曾遇到有人解决类似问题是屏蔽异常消息或者屏蔽ASSERT,并没从根源去消除为什么产生了异常。
3.2.3 报错点发生在第三方库内部
软件报错的地方是在第三方库,而第三方库有没有源代码或不熟悉
如果集成的第三方库没有源代码,则把这个问题上报给第三方,让第三方给出内部出错的原因,更新库或者配合抓日志分析。如果第三方库有源代码的话,可分析第三方代码,增加日志或检查传入第三方库函数的参数是否正确,是否合法;大多数时候,是错误地传入了不合适的参数给第三方库。检查使用第三方的时序是否正确,在软件系统中,时序是一个非常重要,同样的函数,同样的代码,如果时序不对,也会导致代码逻辑紊乱。不过现在提供库或者SDK,一般都有技术支持,也可直接寻求帮助。
3.2.4 软硬件结合导致的无法定位的问题
在嵌入式系统中,有时候会出现硬件异常导致软件状态或逻辑错误,硬件人员很难根据有限的信息判断硬件到底怎么了,通常软件和硬件就会反复的踢皮球。但是用户角度看到的异常是在软件这边。
由于硬件团队对客户现场的设备,通常没有检测手段来判断是否真是硬件问题的,软件团队最好能够通过日志配置,确认硬件故障单元。或者直接将坏机寄回硬件部门,软件配合复现问题,以帮助硬件团队判断。
硬件故障问题,需要特别关注供电、时钟信号,复位时间等,曾经遇到几次因为串口漏电出去导致外部传感器复位异常的问题。总之,软硬件的交合处,是容易扯皮的地方,这需要软件人员也同时了解硬件的工作原理,在出故障时,能够更好的判断是软件异常,还是硬件真的有故障。
还有一个商业上的问题,如果客户感受到是硬件的问题,需要回收设备,会造成很大的经济损失。一般情况下是软件想办法规避异常,毕竟软件复制不需要成本。
全部0条评论
快来发表一下你的评论吧 !