lhwaizhu 发表于 2013-6-4 17:34:58

请教 《嵌入式实时操作系统分uCOS-II原理及应用 >

本书的P146 例5-6
使用一个信号量实现独占式访问资源而出现了任务优先级反转的应用实例:


/************************Test*************************************/
#include "includes.h"
#defineTASK_STK_SIZE   512                                //任务堆栈长度
OS_STK   StartTaskStk;                        //定义任务堆栈区
OS_STK   MyTaskStk;                        //定义任务堆栈区
OS_STK   YouTaskStk;                        //定义任务堆栈区
OS_STK   HerTaskStk;                        //定义任务堆栈区
INT16S   key;                                                //用于退出的键
char*s1="MyTask正在运行";
char*s2="YouTask正在运行";
char*s3="HerTask正在运行";
char*ss="MyTask请求信号量";
INT8U err;                                               
INT8U y=0;                                                //字符显示位置
INT32U Times=0;                                       
OS_EVENT *Semp;                                                //定义事件控制块
voidStartTask(void *data);                                //声明起始任务
voidMyTask(void *data);                                //声明任务
voidYouTask(void *data);                                //声明任务
voidHerTask(void *data);                                //声明任务
/************************主函数*********************************/
voidmain (void)
{
    OSInit( );                                                //初始化uCOS_II
    PC_DOSSaveReturn( );                                //保存Dos环境
    PC_VectSet(uCOS, OSCtxSw);                                //安装uCOS_II中断
    Semp = OSSemCreate (1);                                //定义信号量
    OSTaskCreate(StartTask,                                //创建任务StartTask
        (void*)0,                                        //给任务传递参数
        &StartTaskStk,                //设置任务堆栈栈顶
        0);                                                //使任务的优先级别为0
    OSStart( );                                                //启动多任务管理
}
/***********************任务StartTask*******************************/
voidStartTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SRcpu_sr;
#endif
    pdata = pdata;
    OS_ENTER_CRITICAL( );
    PC_VectSet(0x08, OSTickISR);                //安装时钟中断向量
    PC_SetTickRate(OS_TICKS_PER_SEC);                //设置uCOS_II时钟频率
    OS_EXIT_CRITICAL( );

    OSStatInit( );                                //初始化统计任务
    OSTaskCreate(MyTask,                        //创建任务MyTask
                (void*)0,                        //给任务传递参数
                &MyTaskStk,        //设置任务堆栈栈顶
                3);                                //使任务的优先级别为3
    OSTaskCreate(YouTask,                        //创建任务YouTask
                (void*)0,                        //给任务传递参数
                &YouTaskStk,        //设置任务堆栈栈顶
                4);                                //使任务的优先级别为4
    OSTaskCreate(HerTask,                        //创建任务HerTask
                (void*)0,                        //给任务传递参数
                &HerTaskStk,        //设置任务堆栈栈顶
                5);                                //使任务的优先级别为5
    for (;;)
    {
        //如果按下Esc键则退出uCOS_II
                if (PC_GetKey(&key) == TRUE)
                {
            if (key == 0x1B)
                  {
                PC_DOSReturn( );
            }
      }
      OSTimeDlyHMSM(0, 0, 3, 0);        //等待3秒
    }
}
/************************任务MyTask*******************************/
voidMyTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SRcpu_sr;
#endif
    pdata = pdata;

    for (;;)
    {
      OSTimeDlyHMSM(0, 0, 1, 200);                 //等待200毫秒                                          
      {
          PC_DispStr(10,++y,
                ss,
                DISP_BGND_BLACK+DISP_FGND_WHITE );
            OSSemPend(Semp,0,&err);                //请求信号量
          PC_DispStr(10,++y,
                s1,
                DISP_BGND_BLACK+DISP_FGND_WHITE );

          OSSemPost(Semp);                //发送信号量
      }
      OSTimeDlyHMSM(0, 0, 0, 200);                //等待200毫秒
    }
}
/************************任务YouTask******************************/
voidYouTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SRcpu_sr;
#endif
    pdata = pdata;   
   
    for (;;)
    {                                          
      PC_DispStr(10,++y,
                s2,
                DISP_BGND_BLACK+DISP_FGND_WHITE );                               
      OSTimeDlyHMSM(0, 0, 0, 300);                //等待300毫秒
    }
}
/************************任务HerTask******************************/
voidHerTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SRcpu_sr;
#endif
    pdata = pdata;   

    for (;;)
    {                                          
      OSSemPend(Semp,0,&err);        //请求信号量      
        PC_DispStr(10,++y,
                s3,
                DISP_BGND_BLACK+DISP_FGND_WHITE );

      for(Times;Times<20000000;Times++)
        {
                OS_Sched();
        }
      
        OSSemPost(Semp);                //发送信号量                         
      OSTimeDlyHMSM(0, 0, 1, 0);        //等待1秒
    }
}
/************************End**************************************/

运行结果为:
            YouTask running
            HerTaskrunning
            YouTask running
            YouTask running
            YouTask running
            MyTaskpend_Semp
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            MyTaskrunning
。。。。。。

我是这么理解的程序执行后,StartTask一直在 OSTimeDlyHMSM(0, 0, 3, 0);        ,MyTask先执行 OSTimeDlyHMSM(0, 0, 1, 200);后YouTask执行,输出            

YouTask running 后 OSTimeDlyHMSM(0, 0, 0, 300);    HerTask执行,输出 HerTaskrunning 后进入Times的for循环,不停的调用 OS_Sched(); 切换任务,
因为MyTask延时200ms    YouTask延时的300ms 那么肯定是MyTask先到时间获得CPU使用权,继续执行,输出 MyTaskpend_Semp 然后才在OSSemPend(Semp,0,&err);
里面,YouTask才获得CPU试用权输出 YouTask running 直到HerTask执行 OSSemPost(Semp) ...
我感觉结果应该是:
            YouTask running
            HerTaskrunning
            MyTaskpend_Semp
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            YouTask running
            MyTaskrunning

请教大家 我什么地方理解错了,谢谢指点了....
页: [1]
查看完整版本: 请教 《嵌入式实时操作系统分uCOS-II原理及应用 >