请教一个例子 任哲《嵌入式实时操作系统分uCOS-II原理及应用 第二版 >

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


/************************Test*************************************/
#include "includes.h"
#define  TASK_STK_SIZE   512                                //任务堆栈长度
OS_STK   StartTaskStk[TASK_STK_SIZE];                        //定义任务堆栈区
OS_STK   MyTaskStk[TASK_STK_SIZE];                        //定义任务堆栈区
OS_STK   YouTaskStk[TASK_STK_SIZE];                        //定义任务堆栈区
OS_STK   HerTaskStk[TASK_STK_SIZE];                        //定义任务堆栈区
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;                                                //定义事件控制块
void  StartTask(void *data);                                //声明起始任务
void  MyTask(void *data);                                //声明任务
void  YouTask(void *data);                                //声明任务
void  HerTask(void *data);                                //声明任务
/************************主函数*********************************/
void  main (void)
{
    OSInit( );                                                //初始化uCOS_II
    PC_DOSSaveReturn( );                                //保存Dos环境
    PC_VectSet(uCOS, OSCtxSw);                                //安装uCOS_II中断
    Semp = OSSemCreate (1);                                //定义信号量
    OSTaskCreate(StartTask,                                //创建任务StartTask
        (void*)0,                                        //给任务传递参数
        &StartTaskStk[TASK_STK_SIZE - 1],                //设置任务堆栈栈顶
        0);                                                //使任务的优先级别为0
    OSStart( );                                                //启动多任务管理
}
/***********************任务StartTask*******************************/
void  StartTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_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[TASK_STK_SIZE - 1],        //设置任务堆栈栈顶
                3);                                //使任务的优先级别为3
    OSTaskCreate(YouTask,                        //创建任务YouTask
                (void*)0,                        //给任务传递参数
                &YouTaskStk[TASK_STK_SIZE - 1],        //设置任务堆栈栈顶
                4);                                //使任务的优先级别为4
    OSTaskCreate(HerTask,                        //创建任务HerTask
                (void*)0,                        //给任务传递参数
                &HerTaskStk[TASK_STK_SIZE - 1],        //设置任务堆栈栈顶
                5);                                //使任务的优先级别为5
    for (;;)
    {
        //如果按下Esc键则退出uCOS_II
                if (PC_GetKey(&key) == TRUE)
                {
            if (key == 0x1B)
                    {
                PC_DOSReturn( );
            }
        }
        OSTimeDlyHMSM(0, 0, 3, 0);        //等待3秒
    }
}
/************************任务MyTask*******************************/
void  MyTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_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******************************/
void  YouTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
    pdata = pdata;     
     
    for (;;)
    {                                          
        PC_DispStr(10,++y,
                s2,
                DISP_BGND_BLACK+DISP_FGND_WHITE );                                 
        OSTimeDlyHMSM(0, 0, 0, 300);                //等待300毫秒
    }
}
/************************任务HerTask******************************/
void  HerTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_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
            HerTask  running
            YouTask running
            YouTask running
            YouTask running
            MyTask  pend_Semp
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            YouTask running  
            MyTask  running
。。。。。。

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

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

请教大家 我什么地方理解错了,谢谢指点了....
...全文
216 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
lbing7 2013-06-05
  • 打赏
  • 举报
回复
一开始进入调度程序 由于MY-TASK的延时,信号量是被HER-TASK拿去了,信号量是不允许抢先的,所以,信号量一直在HER-TASK手里 直到他主动释放.
u010957713 2013-06-05
  • 打赏
  • 举报
回复
为什么在 HerTaskrunning后 MyTask pend_Semp前会有三个YouTask running 啊? MyTask延时200ms ,YouTask延时300ms,在HerTask不停的调用OS_Sched()的时候,肯定是MyTask延时先到,然后会打印出MyTask pend_Semp然后才卡在OSSemPend函数里等待HerTask释放信号,这期间会打印出YouTask running,HerTask释放信号后,MyTask打出MyTask running。 谢谢了
u010957713 2013-06-05
  • 打赏
  • 举报
回复
您好,我的意思是: 当HerTask在Times那个for循环里不停的调用OS_Sched()时,MyTask延时200ms到了的时候,获得CPU使用权继续执行,输出ss后,然后卡在OSSemPend(Semp,0,&err);等待信号量...... 我不明白为什么没有输出ss啊?

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧