5948|23

2

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

一个任务异常挂起(有相关的定位数据),求进一步的定位方法 [复制链接]

操作系统:VxWorks,CPU:MPC860,IDE:Tornado2.0
现象:
1.程序(此程序很大有几十个任务运行)运行一段时间后异常复位,每次复位之间的时间间隔无规律,有时半个小时,有时2个小时,有时5,6个小时。
2.通过打印了解到,是由于一个任务tlongtimer被异常挂起(suspended)了,该任务1S执行一次,主要执行两个函数:A(先),B(后),即:
tlongTimer
{
  A;
  B;
  delay(1s);
}

又由于需要,A和B两个函数都用了两个二进制信号量(Mutex1,Mutex2)与其他的函数进行互斥,即
A                                         
{
  semtake(Mutex1);
  semtake(Mutex2);
..................
  semGive(Mutex2);
  semGive(Mutex1);
}

B
{
  semtake(Mutex1);
  semtake(Mutex2);
..................
  semGive(Mutex2);
  semGive(Mutex1);
}

这里我个人认为有必要介绍一下另外一个任务的情况:tShortTimer,10ms执行一次,它的优先级和tLongTimer一样,它主要执行一个函数C,但C只用了Mutex2与A和B进行互斥,即
C
{
semTake(Mutex2);
....
semGive(Mutex2);
}

3.当出现tlongtimer被挂起后,我用tt命令查看了它的调用栈,发现被挂起之前最后调用的函数是A的semGive,或者B的semGive,至于是semGive哪个信号量,不知道(有方法可以定位出来吗?)

4.再用ti命令查看tLongtimer的TCB信息,打印出N个(大概30多个,有什么R31,R3....,当然有SP和PC)寄存器的值(我不知道绝大部分的寄存器代表什么意思,所以无法定位,有资料可以看吗?),同时还打印出出现异常时该任务的PC地址,我用lkaddr查了一下,该地址对应的函数就是semGive。

我的问题:
收集到这些数据后,我感觉离异常的根因很近了,但又觉得很远。
1.是不是因为采用了二进制信号量?因为我看VxWorkx的帮助文档,说二进制信号量主要用于同步,而互斥信号量用于互斥,但我个人觉得二进制信号量这样用应该也可以起到互斥的作用。
2.是不是tLongtimer的堆栈信息被其他的任务或自身的函数改写了?导致信号量的ID为无效值,所以semGive失败?

定位到这里,我不知道该如何定位下去了,还需要采集其他数据吗?如何采集(用什么命令)?还有什么好的定位策略吗?
这个鸟问题烦了我10多天了,请各位大虾帮忙拯救我



最新回复

从简易代码看,逻辑上藐视没有问题。那问题很有可能出在: 1. 某函数非法改写了mutex的内容 2. 某函数非法覆盖了mutex所在的区域 3. 堆栈被某函数非法改写了   详情 回复 发表于 2009-3-31 09:20
点赞 关注

回复
举报

1

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
什么时候eeworld也变冷了?还是觉得问题多分太少?那我再加分
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
感觉LZ的程序逻辑上有问题
从现象上看 是没有规律的 也就是说这种现象是由一种随机出现的事件引起的
看一下两个任务 一个是1S执行一次 一个是10S执行一次
而且 从现象上推断 估计两个任务的执行时间长度肯定是不规律的
出现这种情况通常都是任务间共享资源互斥逻辑上出现问题
不妨在程序中适当输出一些打印信息 例如把每次获取和释放信号量之后的情况打印出来 判断信号量是否获取成功之类的信息

然后在超级终端里捕获一下LOG 对比对比  也许能发现任务死锁的原因
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 
谢谢15楼的兄弟共享的调试方法,非常不错的文章,思路清晰,定位准确,值得学习!
同时,提个问题,这种定位方法是不是需要CPU支持呢?怎么知道哪些CPU支持这种调试方法?
你们说的OCD是集成在CPU内部的吧?
还是说OCD是我需要额外去买的器件?我很想用这种方法去定位我的那个鸟问题!


我非常赞成FireAngel关于去定位寄存器的说法,但是
r0     =        0   sp     =  2692420   r2     =        0    r3     =        0
r4     =        0   r5      =        0       r6     =        0    r7     =        0
r8     =        0   r9      =        0      r10    =        0    r11    =        0
r12    =        0   r13    =        0      r14    =        0    r15    =        0
r16    =        0   r17    =        0      r18    =        0    r19    =        0
r20    =        0   r21    =        0      r22    =        0    r23    =        0
r24    =        0   r25    =        0      r26    =        0    r27    =        0
r28    =        0   r29    =    ffffffff      r30    =   b030    r31    =  17e0700
msr   =  b030     lr     =        0       ctr    =        0     pc     =   1423c0
cr     = 20000043  xer =        0
这些寄存器的含义是什么?有没有说明文档?发给小弟,谢谢!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

5
 
从信号量的使用上来说,不应该用二进制信号量进行代码互斥,而应该使用互斥的信号量来保护。二进制信号量谁都可以take和give,很难保证不出问题。
当然这个一般不会出现导致异常的情况,除非其他任务中有对信号量删除操作之类的。
出异常后,应该会有一段提示出错的信息的,查一下。同时看一下任务堆栈有没有溢出之类的,很多情况下异常都跟堆栈溢出有关
 
 
 

回复

5

帖子

0

TA的资源

一粒金砂(中级)

6
 
锁的顺序不太对像,会不会锁起了?
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

7
 
2楼的是说,任务死锁吗?
你的论据呢?
怎么样可以证明是任务死锁呢?
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

8
 
根据异常堆栈,结合addr2lineppc.exe小程序可以定位到哪一行调用被挂起.
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

9
 
4楼兄弟的意思我明白,有一个任务是10ms级的,如果要输出打印的话,似乎太多了吧?
兄弟你说我的程序逻辑似乎有问题,我曾经这么觉得,但有找不出哪里有问题,
或者你能帮我找一个特例说明我的程序逻辑有问题?

addr2lineppc没有用过,5楼的兄弟能不能说得更细些,我只能得到一个任务的调用函数之间的关系,如何能得到函数中局部变量的地址和值,有办法吗?
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

10
 
从逻辑上看来,两个进程之间这样是没问题的,不应该导致死锁。
有没有这样的可能:tShortTimer负载太重,以至于有时候不能在10ms内完成,新的中断又来了,导致自己挂在自己上面。这个时候tShortTimer无法释放mutex,导致两个进程都挂在mutex2上?

我觉得可以如下调试试试看:
1), 将tShortTimer中工作屏蔽掉,只是semTake后semGive,看会不会出现类似错误。
2), 将tlongtimer中A和B的工作屏蔽掉,只是semTake后semGive,看会不会出现类似错误
3), 将tlongtimer和tShortTimer中的工作都屏蔽掉,只是semTake后semGive,看会不会出现类似错误
4), 如果能确定是tLongTimer或tShortTimer引起的,在慢慢往里面回复以前的操作,反复实验,这样应该能找出问题来。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

11
 
能否尝试将别的任务先不启动,只运行这几个任务,也许问题不一定是在这里。
关于调试查看寄存器,我不知道怎么发给你,所以就贴到我的博客中了,你看看,也许有用。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

12
 
mark
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

13
 
记号。
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

14
 
楼上的兄弟,你说的没错,是需要OCD支持的。事实上,你没有OCD怎么调试呢?
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

15
 
用仿真器当然好啊
不过那东西好贵呀
我们这边一般都是轮着用
所以通常都是通过分析代码和SHELL接口调 其实有很多问题都可以通过分析代码搞定
LZ加油啊
解决了之后定要把分析方法拿来共享一下哈
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

16
 
觉得楼主的这个问题挺有意思的
今天恰好有时间 就在PC上sim了一下
写的代码很简单
除了信号量操作之外只加了空的循环操作
因为要看看输出的结果 所以延时上也比LZ的10ms多了很多
跑了一个下午 没出问题
所以怀疑可能是LZ代码中其他的操作引起的问题或者阻塞
8楼兄弟提出的方法不错  建议楼主试试看 :)
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

17
 
白天忙所以只有晚上看论坛。谢谢各位大侠出的点子,挺感动的,当一个人陷入困境的时候,有其他人的帮助,这种感觉真好。

7楼说的Mark和9楼说的记号,是一种工具还是一种调试手段?能说仔细点吗?

谢谢8楼和11楼的仁兄出点子,现在基本上可以排除是任务死锁造成的了,我怀疑是任务堆栈被异常改写,所以semGvie释放了一个无效的信号量。
10楼的兄弟,麻烦你把资料传给我,我的邮箱是hddream@163.com或者帮你的博客网址给我,谢谢了!

现在最重要的:定位数据堆栈被异常改写有什么好的、快速的调试手段或方法吗?
(数据断点也可以啊,怎么玩?)


 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

18
 
Mark的意思就是先做个记号,等会在回来看这个问题。
调试栈被修改是比较麻烦的问题哦。你不是可以用tt打印出来么?应该能看到一层层下来的调用关系啊。作为一个底层的programmer,错误定位到一定的方位后,通过读代码找出代码中的问题也是很重要的能力。
另外,你可以看看异常相关的寄存器,至少你能看出发生了什么异常,另外就是发生地址。

抱歉啊,860太古老了,从我工作开始,就没有机会接触过。但是应该跟其他MPC相似吧?
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

19
 
数据断点,就是硬件断点的一种啦,是硬件提供的一种调试能力,一般是CPU提供1-2套寄存器,将你要观察的地址设置好,下次针对该地址的有读/写操作,就会发生中断,然后你可以看到是谁访问了那里。挺好的方法。

另外还有硬件程序断点,类似上面,将代码的地址设置到寄存器里,下次PC跑到这的时候就断住了。跟软件断点不同的是,软件断点一般是调试器通过修改内存中的代码,插入调试代码后实现的。硬件断点无需这样。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

20
 
我的博客在eeworld上,你把鼠标移动到我的用户名上,就会显示这个链接的。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表