uC/OS-II互斥信号量与任务优先级反转

一. 任务优先级反转的概念

当任务以独占方式使用共享资源时,会出出低优先级任务先于高优先级任务而被运行的现象,这就是所谓的任务优先级反转。
例如:

1. 任务A和任务C都要使用同一共享资源S,现在假设任务A和任务B都在等待与各自任务相关的事件发生而处于等待状态,而任务C正在运行,且在t1时刻取得了信号量的并开始访问共享资源S。

2. 如果在任务C使用共享资源S过程中的t2时刻,任务A等待的事件到来,那么由于任务A的优先级别高于任务C,所以任务A就剥夺C的CPU而进入运行状态,而使任务C中止运行,这样C就失去了释放信号量的机会。

3. 如果任务A在运行中的t3时刻也要访问共享资源S,但是由于任务C还未释放信号量,因此任务A只好等待。

4. 上面三步出没什么问题,但是如果在任务C继续使用共享资源S过程中的t4时刻,任务B所等待的事件也来临了,由于任务B的优先级也高于任务C,任务B当然要剥夺任务C的CPU而进入运行状态,任务C则只好等待。

5. 同样,任务A也只有等待B运行结束,并且任务C释放信号量的t6时刻才能运行。

综上所述,低优先级任务B反而先于高优先级的任务A运行,这种现象叫做任务优先级的反转。

用代码表示如下:

//优先级 MyTask > YouTask > HerTask
void  MyTask(void *pdata)
{
    for (;;)
    {
        OSTimeDlyHMSM(0,0,0,200); /* 等待200ms */
                    
            OSSemPend(Fun_Semp, 0, &err); /*request signal */
            
            /* Do something */
            
            OSSemPost(Fun_Semp); /* send signal */

      OSTimeDlyHMSM(0,0,0,200); /* 等待200ms */
       
    }
}

void  YouTask(void *pdata)
{
    for (;;)
    {
                /* Do something */
                OSTimeDlyHMSM(0,0,0,300); /* 等待300ms */
        
    }
}

void  HerTask(void *pdata)
{
    for (;;)
    {
            OSSemPend(Fun_Semp, 0, &err); /*request signal */
                
                for(Times; Times<20000000;Times++)
                {
                    /* Do something */
                    OS_Sched();    
                }
                
                OSSemPost(Fun_Semp); /* send signal */
                
                OSTimeDlyHMSM(0,0,1,0); /* 等待1s */
        
    }
}

运行结果如下:


二. 互斥信号量

从上面的例子发现:
使用信号量的任务是否能够运行, 受到任务的优先级别以及 是否占用信号量两个条件约束, 而信号量的约束高于优先级别的约束

于是,当出现低优先级别的任务与高优先级别的任务使用同一个信号量,而系统中还存在其他中等优先级别的任务时,如果低优先级别的任务先获得了信号量,就会使高优先级别的任务处于等待状态,而那些不使用该信号的中等待优先级别的任务却可以剥夺低优先级别任务的CPU使用权而先于高优先级别的任务而运行了。

解决问题的办法之一是:

使获得信号任务的优先级别在使用共享资源期间暂时提升到所有任务最高优先级的高一个级别上(最高优先级+1),以使该任务不被其他任务所打断,从而能尽快地使用完共享资源并释放信号量,然后在释放信号量之后,再恢复该任务原来的优先级别。

互斥信号量:

互斥信号量就是按上面的解决办法设计的,在描述互斥信号量的事件控制块中,除成员OSEventType=OS_EVENT_TYPE_MUTEX以表明这是一个互斥信号量,成员OSEventCnt被分成了低8位和高8位两部分;

低8位用来存放信号值(0xff时信号有效,即信号量尚未被任何任务所占用;否则信号为无效);

高8位用来存放为了避免出现优先级反转现象而要提升的优先级别。

相关操作:

1. 创建互斥型信号量
//参数prio表明要提升的优先级别
OS_EVENT  *OSMutexCreate (INT8U prio, INT8U *err);
2. 请求互斥型信号量
void  OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err);
3. 发送互斥型信号量
INT8U  OSMutexPost (OS_EVENT *pevent);
4. 获取互斥型信号量的当前状态
INT8U  OSMutexQuery (OS_EVENT *pevent, OS_MUTEX_DATA *pdata);
5. 删除互斥型信号量
OS_EVENT  *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *err);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值