uC/OS-II windows下寄生仿真问题 后记

来源:互联网 发布:短域名扫描 编辑:程序博客网 时间:2024/05/16 07:44

(本文原创,转载请注明出处)


自《uC/OS-II Windows下虚拟的问题》发表以后,很多朋友给我留言,:),在此,谢谢大家的批评指正。希望大家直接在我的Blog上留言,少用QQ留言,这些技术问题,在Blog上讨论,会越辩越明。在QQ上留言,很容易一边倒。

特别是“探路者”网友给我的留言,这里贴出来,供大家一起研究:


2011-08-27 08:49:22  探路者:

uC/OS-II Windows下虚拟的问题:我觉得你的分析存在问题的。
2011-08-27 08:51:47  探路者:
对于Windows和Linux来说,进程是操作系统能够调度的最小单位,线程是进程能够调度的最小单位。
2011-08-27 08:54:21  探路者:
ucosii程序,一个整体,是作为操作系统能够调度的最小单位-进程来运行的,操作系统不会认识到ucosii程序内部的运作,比如多线程。
2011-08-27 09:01:25  探路者:
对于操作系统来说,只有进程切换,而没有线程切换。
2011-08-27 09:01:52  探路者:
对于单个进程来说,才会存在线程切换。
2011-08-27 10:06:04  探路者:
对于第一个问题:不存在单独的线程切换,只存在进程的切换。虽然ucosii整体(进程)的实时性得不到最优的保证,但是ucosii整体(进程)的运行的完整性是得到保证的。
2011-08-27 10:09:24  探路者:
对于第二个问题:既然访问共享资源,那么就一定会考虑互斥的问题了。访问windows和linux操作系统的临界资源的前后,考虑加锁和解锁,也是一件正常不过的事情。
2011-08-27 10:14:55  探路者:

请雪松大侠分析清楚,我对这个问题也是很着急,因为我就是这样在用,而且想应用到一个控制系统中。如果我贸然使用,会出现《惊魂动车组》,就麻烦了。 



这里我不想多说,《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);

    }

}


这三个任务是再简单不过的任务了。现在假设任务1的优先级别最高,任务2的优先级别次之,任务3的优先级别最低。printf这个函数都会往屏幕上输出,windows 为了防止输出错乱,printf 函数内部是有一个 windows 的锁,用来防止输出到屏幕上的数据错乱。正因为有了这个锁,我们看到的输出信息不会有类似以下的输出:

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的系统核心里停下了。欢迎拍砖!!!


(本文原创,转载请注明出处)


原创粉丝点击