主要针对Liteos系统稳定性测试过程中的一些常见问题进行总结,介绍相应的排查思路以及相关的命令、日志信息等。
方便测试人员对问题的初步定位分类,也作为研发人员排查问题的参考,提高问题的排查效率。
可以通过help查看liteos系统当前支持的命令,其中常用命令及其意义如下
崩溃设备的现象一般为:设备ping
不通,sadp
搜索不到,串口没反应,且串口最后打印信息类似下图:
上图中信息解析如下:
1、图中uwExcType代表死机类型,具体数值信息意义如下
2、“puwExcBuffAddr pc = 0x8087aeb4”为设备的崩溃地址,此时需要根据设备程序属性(程序包路径、中英文、中性标配)确认设备对应的.asm文件确认设备崩溃的语句(由于踩内存等原因,这个pc 值有事可能无效)。
然后从“backtrace begin”开始下方的traceback代表的是死机时的调用栈信息。
lr为死机所在函数的调用函数链信息;
3、上图中设备崩溃时的任务列表信息为:
4、pcTaskName代表设备的崩溃线程
注意:设备在不接串口的时候崩溃(魔法键也没有响应),
会将崩溃信息存放在flash中,
这个时候需要将设备重启(重启前关注设备电源连接灯和网络灯量灭情况),
输入excInfo命令获取信息,保存打印。
设备崩溃信息最多能保存6次,故每次测试前需要使用erase_excInfo进行擦除,擦除之后可以重新保存6次,崩溃信息内容形如下截图:
系统卡住的设备与系统崩溃的设备不通的是卡住设备是没有崩溃打印信息的,所以需要使用魔法键进行确认设备的相关信息。
魔法键相关命令解析如下:
查看帮助:ctrl+break+h
堆栈回溯:ctrl+break+b
内存信息:ctrl+break+m
中断信息:ctrl+break+x
任务信息:ctrl+break+t
注意:系统卡住设备的其他注意事项同系统崩溃的设备。
空函数指针访问的现象又称二次初始化,
是设备在启动之后再次调用空指针会从0地址重新执行,
即设备会进行二次初始化,从而导致设备异常死机。
打印信息如下图:
一般造成造成此类的原因有两类:
A、 空指针访问,例:
char *p = NULL;
*p = 1;
B、 空函数指针访问,例:
typedef char (*test_func)(int);
test_func pFun = NULL; /*测试空函数指针*/
pFun(2);
内存泄露设备一般会出现以下一个或者多个现象:
1、free显示的剩余内存在逐渐减少。
2、task信息中线程数量比设备正常情况下多十几个。或者是task信息下某一个线程起来了很多次。
3、设备打印信息中会存在内存不足或者栈溢出等类似打印。例:
[osMemAllocWithCheck] No suitable free block, require free node size: 0x1001c
栈踩内存的现象跟设备崩溃类似,唯一特别的是task
的信息,以下图为例:
其中线程名为ipc_sdk30900
,即sdk
重启线程。
StackSize = 0x20000
(创建该任务时分配的栈大小)
WaterLine = 0x1fffc(水线,目前为止该任务栈已经被使用的内存大小)
StackPoint = 0x80bce27c(任务栈指针, 指向该任务当前的地址)
TopOfStack = 0x814826a0(栈顶)
MaxStackPoint = Top0fStack + StackSize (得到该任务栈最大的可访问地址)
故:
A、对比WaterLine和StackSize, 若WaterLine大于StackSize,说明该任务踩内存
B、观察StackPoint ,理论上 StackPoint<= MaxStackPoint && StackPoint >= TopOfStack,若不在这个范围内,则说明任务栈踩内存
函数osShellCmdMemcheck将会对系统动态内存池所有的节点进行遍历,如果所有节点正常则会打印log:“memcheck over, all passed!”,否则将打印相关的错误信息。
如果已知一个全局变量被踩内存,在其对应的sample.map
文件中找到该全局变量所在的地址。
并且特别注意该地址之前最近被使用的变量,因为有极大概率是前面变量在使用过程中内存越界,才踩掉了这个全局变量。
如图在sample.map
文件中表现的现象为g_uwEraseMap
被踩,需要特别注意分析g_uwEraseCount
这个全局变量的使用情况,观察是否存在某处,对全局变量g_uwEraseCount
进行了越界操作。
通过cpup 1
可以查看当前设备的cpu
利用率,如果总cpu
利用率非常高,则需要通过task
命令查看具体线程的cpu
利用率。
如果出现某一线程的cpu
利用率达到90%
以上如下图,基本可以确认是线程死循环了。
通过task
+线程ID
查看当前线程运行的函数调用堆栈,对照davinci.asm
进行搜索查询,来查到死循环的调用接口。
死锁设备一般会卡在某一或几个功能执行过程中,
但设备没有崩溃,对应被死锁的线程处在Pend
状态,
此时需要通过task
+线程ID
查看当前线程运行的函数调用堆栈,
对照davinci.asm进行搜索查询,来查到设备死锁的调用接口。
由于Liteos使用的Lwip网络协议栈是没有对我们开放的,所以一些网络排查手段有限,如果涉及到协议栈如tcpip_thread等的问题需要提交给海思协助进行排查。
所以需要对问题进行详细的了解:
1、确认什么操作引起的设备问题
2、确认网线连接是否正常,网线水晶头/网口连接是否松动。
3、确认MAC地址的设置是否合法,第六个字节(6th byte)不能为奇数,奇数表示该MAC地址为多播地址。
4、确认是否有其他网络设备与摄像机IP冲突。 即将设备从网络中断开,然后再ping该IP地址,如果可以ping通,则说明网络中有其他设备与该设备有相同的IP地址。
5、查看网口连接状态、网卡模式、网卡中断、连接状态和数据收发情况:
hwi确认MAC地址的设置合法查看中断情况,多次查看,观察是否有增长。
ifconfig查看网卡状态
netstat查看发送、接收队列中是否有数据累积,socket使用量,默认最大128
6、确定是否受到网络环境的影响
查看与问题设备同处一个网络的设备,有无同样的问题。
设备与PC直连,问题消失,而接回原网络环境问题依然存在,则与网络环境有关。
7、尝试恢复:ifconfig down/up重启网卡一次,看网络能否恢复。
8、网络抓包:抓包查看客户端连接设备的信息是否发出,以及设备是否有回复。
9、收集版本信息:prtHardInfo
问题描述:系统测试搭建了70台设备做稳定性软重启测试,在某次启动之后,出现同局域网内54台设备同时掉线(分布在两台同一局域网交换机上),web无法预览,设备pc ping不通设备,并发现两台设备串口卡住,当拔掉其中两台卡主的设备(同一交换机)的网线之后,同一交换机上的其他设备恢复正常。
问题分析:
1)研发本地模拟设备崩溃,通过内存不断消耗,最终导致设备崩溃,崩溃是同一交换机上Liteos设备和PC、PC与PC、PC与linux设备都互相ping不通,具体网络拓扑图如下:
说明:
1)当只使用NETGEAR交换机的时候,Liteos设备在崩溃之后,PC、设备相互之间是无法访问的,且本地抓包都抓不到对端ping过来的包;
2)当只使用H3C交换机组成的局域网的时候,发现Liteos设备崩溃之后,PC与设备相互ping是正常的;
3)当H3C交换机接在NETGEAR交换机的设备,NETGEAR上的Liteos设备崩溃,发现经过H3C的设备是可以ping通的,不经过H3C的设备或者PC是无法ping通的。
交换机差异:
802.3x规定了一种64字节的“PAUSE”MAC控制帧的格式。当端口发生阻塞时,交换机向信息源发送 “PAUSE”帧,告诉信息源暂停一段时间再发送信息。在实际的网络中,尤其是一般局域网,产生网络拥塞的情况极少,所以有的厂家的交换机并不支持流量控制。高性能的交换机应支持半双工方式下的反向压力和全双 工的IEEE802.3x流控。有的交换机的流量控制将阻塞整个LAN的输入,降低整个LAN的性能;高性能的交换机采用的策略是仅仅阻塞向交换机拥塞端口输入帧的端口,保证其他端口用户的正常工作。
原因确认:
根据上述交换机流控差异,初步怀疑是Liteos设备崩溃之后,Mac和Phy还在正常工作,此时设备Tx发送流控还是开启的,会一直向交换机发送pause帧,最终导致交换机阻塞。
关闭崩溃设备tx流控之后,网络正常,验证通过。
问题解决:
Liteos设备崩溃时,关闭硬件TX流控。
问题描述:以HIKVISION协议接入,NVR出现断链问题。打印信息如下图(中间有非常多的端口打印被省略):
问题原因:设备的套接字被占用完,导致其他的网络连接无法建立
由于liteos问题排查手段有限,所以设备在升级前一定要将打印等级放开,否则很多问题会不好排查。其中一些特殊问题的打印信息如下:
注:sdk升级线程名字为ipc_sdk30b00,sdk重启线程名字为ipc_sdk30900。
1、升级版本不匹配打印信息:
[UPG][RT_ERROR][src/sys_firm_upgrade.c][firm_version_ctrl][1282]:firm ver=0x5030009, dev ver=0x5040000 version denied!
软件版本为5.3.9,升级库相关的版本为5.4.0。
2、设备类型未添加时,升级错误的打印信息:
UPG_STAT_OK == (pUpgInfo->eMapStat = firm_class_check(pUpgInfo)) fail warner eErrVal pUpgInfo->eMapStat=0x00000042!
sys_firm_class_G1_IPC.c中未添加设备型号。
3、次类型不匹配的打印信息:
[UNI_IF][ERROR][UPG_ASSERT] 0 == memcmp(pDevParam->bMinorTypeId, pFirmFlag->bMinorTypeId, sizeof(pFirmFlag->bMinorTypeId)) fail to eRetVal UPG_STAT_MISMATCH_MINORTYPE=0x00000039!
4、升级文件的对应路径下文件不存在:
(1)<4>Node totlen on flash (0xffffffff) != totlen from node ref (0x00000034)
<4>Node totlen on flash (0xffffffff) != totlen from node ref (0x00000138)
(2)[firm_class_check][2327]:tClassVec[0].iov_len == sys_file_readv("/home/_cfgUpgClass", 0, tClassVec, ((((void *)0) != (tClassVec)) ? (int)(sizeof(tClassVec) / sizeof((tClassVec)[0])) : (0)), ((void *)0), ((void *)0), ((void *)0)) fail return eErrVal UPG_STAT_ERR_DRV_CLASS=0x000000d7!
一些特殊问题以及特殊的打印信息如下:
1、设备fd超过最大值256的打印信息:
[ERR] system_shell_init[200] open /dev/shell failure fd:-1!
2、设备被远程telnet连接打印,打印信息会被截断,串口打印信息如下:
Accept telnet client connection from 10.17.113.18:58609
client handle thread creat success!
3、vgs问题打印信息(VGS调用VB接口崩溃打印信息):
[11-02 21:27:25]ASSERT failed at:
[11-02 21:27:25] >File name: video_buf.c
[11-02 21:27:25] >Function : VB_Handle2PoolId
[11-02 21:27:25] >Line No. : 1289
[11-02 21:27:25] >Condition: HI_NULL != s_apstPools[VB_H2POOLID(Handle)]