zoukankan      html  css  js  c++  java
  • ucosIII_使用互斥信号量解决优先级反转问题

    ucosIII_使用互斥信号量解决优先级反转问题。用于实现对临界资源的独占式处理,降低优先级反转带来的影响。

    信号量的二值信号量可以作为一个标志flag,当两个任务访问同一个资源时,进行加锁解锁。如果当多个任务要访问同一个资源,使用二值信号量很容易带来优先级反转的问题,而这种问题,是操作系统极其不期望出现的问题(破坏任务的预期顺序,可能会导致严重的后果),所有引入互斥信号量解决优先级反转问题。

    1.什么是优先级反转

    假设有3个任务,优先级从高到底分别是任务H(high)M(middle)L(low)。

    任务H和任务L使用互斥信号量访问同一临界资源,任务M不使用临界资源。

     图1 任务HML发生优先级反转

    图1(1):L任务正在使用某临界资源(信号加锁),H任务被唤醒,执行H任务。但L任务并未执行完毕,此时临界资源还未释放(互斥信号量还处于加锁状态,即使优先级更高的任务也无法访问这个临界资源)
    图1(2):这个时刻H任务也要对该临界资源进行访问,但L任务还未释放资源,由于保护机制,H任务进入阻塞态,L任务得以继续运行,此时已经发生了优先级翻转现
    图1(3):某个时刻M任务被唤醒,由于M任务的优先级高于工任务,M任务抢占了CPU的使用权,M任务开始运行,此时L任务尚未执行完,临界资源还没被释放
    图1(4):M任务运行结束,归还CPU使用权,L任务继续运行。
    图1(5):L任务运行结東,释放临界资源(信号解锁),H任务得以对资源进行访问,H任务开始运行。

    说的通俗点就是,任务H和任务L都会访问一个临界资源区,通过互斥信号量加锁解锁没问题。任务H和任务L会互相等待对方加锁或解锁,这个也没问题。但是任务M优先级比任务L优先级高,本来任务H等着任务L解锁互斥信号量呢,结果CPU不去执行任务L,CPU被任务M抢了,任务H本来是想等任务L的信号呢,现在还要等任务M执行完,才能让任务L解锁信号量。那任务H可是最高优先级啊,任务H不能忍了。所有任务H把任务L的优先级提到和自己一般高(通过互斥信号量自动完成),这样任务M无法打断任务L了。等任务H获得了这个信号量,在把任务L的优先级调回原来的级别。

    那到底什么是优先级反转呢?

    我的理解:两个任务使用互斥信号量访问同一资源,由于其他任务抢占了其中某个任务的CPU使用时间,导致另一个任务不能及时接收或发送这个互斥信号量。使得一个任务等待互斥信号量的时间变长。

    使用互斥信号量解决上面这个问题:

    图2 使用互斥信号量解决优先级反转

    图2(1):L任务正在使用某临界资源,L任务正在使用某临界资源,H任务被唤醒执行H任务。但L任务并未执行完毕,此时临界资源还未释放
    图2(2):某一时刻任务也要对该资源进行访问,由于保护机制,H任务进入塞态。此时发生优先级继承,系统将L任务的优先级暂时提升到与H任务优先级相同,L任务继续执行
    图2(3):在某一时刻M任务被唤醒,由于此时M任务的优先级暂时低于L任务,所以M任务仅在就绪态,而无法获得CPU使用权。
    图2(4):L任务运行完毕,H任务获得对资源的访问权,H任务从阻塞态变成运行态,此时L任务的优先级会变回原来的优先级。
    图2(5):当H任务运行完毕,M任务得到CPU使用权,开始执行
    图2(6):系统正常运行,按照设定好的优先级运行

    2.互斥信号量的API 

     文件os_mutex.c

    2.1创建信号量

    void  OSMutexCreate (OS_MUTEX  *p_mutex,
                         CPU_CHAR  *p_name,
                         OS_ERR    *p_err)

    第一个参数是互斥信号量,我们要先定义一个

    OS_MUTEX MyMutex; //定义一个互斥信号量

    第二个参数是互斥信号量的名字

    第三个参数是记录 返回值的,用于保存错误信息

    OS_ERR MutextErrRet//定义一个互斥信号量错误返回值

    2.2发送互斥信号量

    void  OSMutexPost (OS_MUTEX  *p_mutex,
                       OS_OPT     opt,
                       OS_ERR    *p_err)

    第一个参数是互斥信号量

    第二个参数默认模式和不使用调度

    第三个参数是记录返回值,用于保存错误信息

    2.3请求信号量

    void  OSMutexPend (OS_MUTEX  *p_mutex,
                       OS_TICK    timeout,
                       OS_OPT     opt,
                       CPU_TS    *p_ts,
                       OS_ERR    *p_err)

    第一个参数是互斥信号量的变量

    第二个参数是请求互斥信号量的超时时间

    第三个参数设置阻塞还是不阻塞

    第四个参数是时间戳

    第五个参数是错误返回值

    2.4删除互斥信号量

    OS_OBJ_QTY  OSMutexDel (OS_MUTEX  *p_mutex,
                            OS_OPT     opt,
                            OS_ERR    *p_err)

    3.互斥信号量的注意事项

    (1) 但是使用互斥量的时候一定需要注意:在获得互斥量后,请尽快释放互斥量,同时需要注意的是在任务持有互斥量的这段时间,不得更改任务的优先级。UCOS的优先级继承机制不能解决优先级反转,只能将这种情况的影响降低到最小,硬实时系统在一开始设计时就要避免优先级反转发生

    (2)互斥量的使用比较单一,因为它是信号量的一种,并且它是以锁的形式存在。在初始化的时候,互斥量处于开锁的状态,而被任务持有的时候则立刻转为闭锁的状态。互斥量更适合于:
        可能会引起优先级翻转的情况。
        任务可能会多次获取互斥量的情况下,这样可以避免同一任务多次递归持有而造成死锁的问题。

    (3)互斥量不能在中断服务函数中使用,因为其特有的优先级继承机制只在任务起作用,而在中断的上下文环境中毫无意义。



    图片引用于野火资料22.1  互斥量的基本概念,关于API的具体使用查看UCOSIII/Source/OS_Mutex.c。在野火文档基础上添加了自己的理解,有不准确的地方希望大佬指正。

  • 相关阅读:
    php类和对象: 类常量
    类和对象:静态属性、静态方法
    类和对象: 构造方法
    类和对象:成员属性、成员方法 — 学习笔记3
    类和对象:创建对象
    类和对象:类与对象定义
    可扩展定制可复用的倒计时插件
    SeaJS入门
    JS可复用的多条件筛选插件
    谁说转载的文章用户就不喜欢了?
  • 原文地址:https://www.cnblogs.com/1024E/p/13416956.html
Copyright © 2011-2022 走看看