(本文原创,转载请注明出处)
自《uC/OS-II Windows下虚拟的问题》发表以后,很多朋友给我留言,:),在此,谢谢大家的批评指正。希望大家直接在我的Blog上留言,少用QQ留言,这些技术问题,在Blog上讨论,会越辩越明。在QQ上留言,很容易一边倒。
特别是“探路者”网友给我的留言,这里贴出来,供大家一起研究:
2011-08-27 08:49:22 探路者:
uC/OS-II Windows下虚拟的问题:我觉得你的分析存在问题的。请雪松大侠分析清楚,我对这个问题也是很着急,因为我就是这样在用,而且想应用到一个控制系统中。如果我贸然使用,会出现《惊魂动车组》,就麻烦了。
这里我不想多说,《uC/OS-II Windows下虚拟的问题》中已经说得非常清楚, 这里举上一个实际的例子:
void task1(void *param)
{
while (1)
{
printf("Haha....you are in task 1.\n");
OSTimeDly(40);
}
}
void task2(void *param)
{
while(1)
{
printf("Haha, you are in task 2.\n");
OSTimeDly(20);
}
}
void task3(void *param)
{
while(1)
{
printf("Haha, you are in task 3.\n");
OSTimeDly(20);
}
}
Haha, you are Haha, in task 2.
you are in task 3.
如果在windows上模拟,使用了windows库里的printf函数,这个锁是无法规避的。为了便于讨论,我们把printf简化为如下伪代码:
int printf(char *fmt, ...)
{
char *lines[MAX_OUTPUT];
*lines = '\0';
...;//output print data to lines;
lockscreen();//acquire lock.
output2screen(lines);
unlockscreen();//release lock.
return ...;
}
本来uC/OS-II运行到任务3的printf语句时如果全部完成,也没什么事情。假设如果运行到lockscreen()时,正在ouput2screen()呢。uC/OS-II觉得你的时间到了,运行任务1去了。如果运行到printf中的lockscreen()时,那么task1就执行不下去了。只能执行其它任务,或者让任务3执行下去,直到unlockscreen()。task1才能继续执行。
我们来细细看一下:
lockscreen()并不是uC/OS-II的锁。
uC/OS-II并不知道task3已经进入了一个临界区域,在windows下的移植里,uC/OS-II的核心会调用SuspendThread()挂起task3,task3并不会自己恢复执行,必须 uC/OS-II的调度算法调用ResumeThread(),task3才能恢复执行。调度算法调用ResumeThread恢复task1执行时,遇到lockscreen,task1进入阻塞状态,这个阻塞状态是windows的阻塞状态,在uC/OS-II核心里,task1仍然是运行态。 但实际上task1已经死了,所有低于task1优先级的任务都Over了。如果 task1是最高优先级任务,那么整个uC/OS-II虽然没有死,但现象就是全部都死了。
我想我讲清楚整个过程了吧。仿真这个过程也很简单,在 VC++上很容易在线这个问题。由于并不是必现的问题,多弄几个printf任务,增大出现的几率。通过thread观察窗口和callstack窗口,可以明显的看到task1和task3都停在了printf里面。在windows的系统核心里停下了。欢迎拍砖!!!
(本文原创,转载请注明出处)