<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />2009年10月16日星期五19:44:43
程序调试
一、调试目的
在前两天编写的shell程序中,出了这么一个问题:shell程序从消息队列读取按键,当读取到enter键时,进入命令执行状态;命令执行完成后,回到输入态,继续读取按键。但是实际执行过程中发现,如果输入错误命令,程序正常执行;但是输入正确命令执行完成以后,会进入一个读取按键的死循环。通过简单调试发现,是消息队列那里出了问题,今天的调试就从消息队列开始。
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
二、ucos的消息队列
1、它是如何创建的?
在操作系统初始化时,调用了OS_QInit(),该函数主要是初始化了OSQFreeList = &OSQTbl[0];并且把各个消息队列控制块链接起来。
然后应用程序调用OS_QCreate()创建自己的消息队列,提供的参数两个:一个是事件控制块,事件控制块包括—类型、指针、等待任务列表等;一个是消息指针数组。创建的过程大概是这样:取出一个事件控制块,类型设置为消息队列,取出一个队列控制块,让事件控制块的指针指向它。然后队列控制块有读指针、写指针、消息数量、队列容量等参数进行初始化。 pq->OSQStart = start; /* Initialize the queue */
pq->OSQEnd = &start[size];
pq->OSQIn = start;
pq->OSQOut = start;
pq->OSQSize = size;
pq->OSQEntries = 0;
2、消息发到消息队列
程序调用OS_QPost()函数将消息发送到队列,实际上消息内容需要程序自己提供内存,消息队列接受内容的指针,将它复制到消息指针数字里,同时调整写指针,指向下一个消息指针。 *pq->OSQIn++ = pmsg; /* Insert message into queue */
pq->OSQEntries++;
3、从消息队列取数据
程序调用OS_QPend()函数从消息队列取消息,实际上是得到一个指针,然后根据指针取到相应的内容,同时还要调整队列控制块的读指针和有效消息数。 pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */
if (pq->OSQEntries > 0) { /* See if any messages in the queue */
pmsg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */
pq->OSQEntries--;
当然,如果没有消息,那就在该队列上等待。
三、调试过程
1、观察事件控制块的参数变化
我定义的事件控制块为KeyValueOSQ,先把它加到观察列表。
在出问题的地方之前设置一个断点,起动调试。
输入一个正确的命令,程序执行输出:输入help,屏幕显示shell支持的其他三个命令。
最后观察KeyValueOSQ:它的队列控制块指针为0x2000,0df0.
同时把消息指针数组加到观察列表。
进入KB_GetChar()函数的内部,调用OS_QPend()从消息队列取数据,一进去,发现 if (perr == (INT8U *)0) { /* Validate 'perr' */
return ((void *)0);
是由于这句话因此返回一个无效指针。Perr没有有效地址。
解决办法:将它设置为一个全局变量。
2、最终的解决方案
开始定义 u8 *perr,这个指针由于没有初始化,是一个随即的值。
改为u8 Err,然后在调用OS_QPend时采用参数,&Err,程序正常运行。
四、收获
1、调试过程中要做好计划,先确定故障的范围,一般来说,结合程序的输出表现、单步调试可以确定故障点。
2、指针的使用一定要注意:使用之前必须先初始化,比如这个程序中我定义了u8* perr。然后在程序中直接调用KeyPtr=OS_QPend(KeyValueOSQ,0,perr);这是一个还未赋值和初始化的指针,它的值是随机的,当它变为0后,这个程序的运行就不正常了。
改为:u8 Err定义,然后这样调用KeyPtr=OS_QPend(KeyValueOSQ,0,&Err),程序的运行就恢复正常了。
文章评论(0条评论)
登录后参与讨论