当前位置:
文档之家› 嵌入式实时操作系统(第10课时)
嵌入式实时操作系统(第10课时)
/*******************************任务MyTask******************************************/ void MyTask(void *pdata) { #if OS_CRITICAL_METHOD==3 OS_CPU_SR cpu_sr; #endif pdata=pdata; for( ; ; ) { OSTimeDlyHMSM(0,0,1,200); //等待200ms { 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);
例4-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 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; OS_EVENT *Semp; //定义事件控制块
/*******************************任务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); //设置µc/os-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
4.3.2 互斥型信号量
互斥型信号量是一个二值信号量,因此也叫做信号。任务可以用互斥型信号量来 实现对共享资源的独占式处理。为了解决任务在使用独占式资源出现的优先 级反转问题,互斥型信号量除了具有普通信号量的机制外,还有一些其他特 性。 pevent OS_EVENT_TYPE_MUTEX OSEventType prio 0xFF OSEventCnt NULL OSEventPtr OSEventGrp 0x00 任 务 等 待 表 0 0 0 OSEventTbl[ ] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
OSSemPost(Semp); }
//发送信号量 //等待200ms
OSTimeDlyHMSM(0,0,0,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); //等待300ms } }
综上所述,任务优先级低的任务B反而先于任务优先级高的任务A运行了。换句 话说,从实际运行的结果来看,似乎任务B的优先级高于任务A了。系统中的 这种现象叫做任务优先级的反转。 之所以出现上述的优先级反转现象,是因为一个优先级别较低的任务在获得了信 号量使用共享资源期间,被具有较高优先级别的任务所打断而不能释放信号 量,从而使正在等待这个信号量的更高级别的任务因得不到信号量而被迫处 于等待状态,在这个等待期间,就让优先级别低于它而高于占据信号量的任 务的任务先运行了。显然,如果这种优先级别介于使用信号量的两个任务优 先级别中间的中等优先级别任务较多,则会极大的恶化高优先级别任务的运 行环境,是实时系统所无法容忍的。
OSTaskCreate(HerTask, //创建任务HerTask (void *)0, //给任务传递参数 &HerTaskStk[TASK_STK_SIZE-1], //设置任务堆栈栈顶指针 5); //使任务的优先级别为5 for( ; ; ) { //如果按下ESC键,则退出µc/os-II if(PC_GetKey(&key)==TRUE) { if(key==0x1B) { PC_DOSReturn(); } } OSTimeDlyHMSM(0,0,d StartTask(void *data); //声明起始任务 void MyTask(void *data); //声明任务 void YouTask(void *data); //声明任务 void HerTask(void *data); //声明任务 /**************************************主函数*******************************************/ void main(void) { OSInit(); //初始化µc/os-II PC_DOSSaveReturn(); //保存DOS环境 PC_VectSet(uCOS,OSCtxSw); //安装µc/os-II中断 Semp=OSSemCreate(1); //定义信号量 OSTaskCreate(StartTask, //创建任务StartTask (void *)0, //给任务传递参数 &StartTaskStk[TASK_STK_SIZE-1], //设置任务堆栈栈顶指针 0); //使任务的优先级别为0 OSStart(); //启动多任务管理 }
嵌入式实时操作系统
第四章 任务的同步与通信
R
4.3 互斥型信号量和任务优先级反转
4.3.1 任务优先级的反转现象
在可剥夺型内核中,当任务以独占方式使用共享资源时,会出现低优先级任务先 于高优先级任务而被运行的现象,这种现象叫做任务优先级反转。 在一般情况下是不允许出现这种任务优先级反转现象的。
任务A(高) 任务A等待的 事件来临 任务A申请的 信号量 任务A因优先级别高于 任务C而运行 任务A因任务C未释放 信号量而等待 任务B等待 的事件来临 任务B(中) 任务C(低)
/***************************************任务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); //等待1s } } /****************************************END*******************************************/
图4-15描述了A、B、C三个任务的运行情况。其中,任务A的优先级别高于任务 B,任务B的优先级别高于任务C。任务A和任务C都要使用同一个共享资源S, 而用于保护该资源的信号量在同一时间只能允许一个任务以独占的方式对该 资源进行访问,即这个信号量是一个互斥型信号量。 现在,假如任务A和任务B都在等待与各自任务相关的事件发生而处于等待状态, 而任务C正在运行,且在t1时刻取得了信号量并开始访问共享资源S。 如果在任务C使用共享资源S过程中的t2时刻,任务A等待的事件已经到来,那么 由于任务A的优先级别高于任务C的优先级别,所以任务A就剥夺任务C的 CPU使用权而进入运行状态,而使任务C中止运行,这样任务C就失去了释放 信号量的机会。如果任务A在运行中的t3时刻又要访问共享资源S,但由于任 务C还未释放信号量,因此任务A只好等待,以使任务C可以继续使用共享资 源S。 以上过程都是正常的,是应用程序设计者意料之中的事情。问题是,如果在任务 C继续使用共享资源S过程中的t4时刻,任务B所等待的事件也来临,由于任 务B的优先级别高于任务C的优先级别,任务B当然要剥夺任务C的CPU使用 权而进入运行状态,而任务C则只好等待。这样,任务A只有当任务B运行结 束,并使任务C继续运行且释放了信号量的t6时刻之后,才能获得信号量而得 以重新运行。