先介绍一下优先级反转的相关知识:

优先级翻转是当一个高优先级任务通过信号量机制访问共享资源时,该信号量已被一低优先级任务占有,因此造成高优先级任务被许多具有较低优先级任务阻塞,实时性难以得到保证。
例如:有优先级为A、B和C三个任务,优先级A>B>C,任务A,B处于挂起状态,等待某一事件发生,任务C正在运行,此时任务C开始使用某一共享资源S。(A和C需要使用共享资源S,B不需要。)在使用中,任务A等待事件到来,任务A转为就绪态,因为它比任务C优先级高,所以立即执行。当任务A要使用共享资源S时,由于其正在被任务C使用,因此任务A被挂起,任务C开始运行。如果此时任务B等待事件到来,则任务B转为就绪态。由于任务B优先级比任务C高,因此任务B开始运行,直到其运行完毕,任务C才开始运行。直到任务C释放共享资源S后,任务A才得以执行。在这种情况下,优先级发生了翻转,任务B先于任务A运行。
这样的话,会导致如果有很多任务处于A和C优先级之间,在一定的条件下,都会优于A先执行。这样的话,A就被长时间阻塞。
解决优先级翻转问题有优先级天花板(priority ceiling)和优先级继承(priority inheritance)两种办法。
优先级天花板是当任务申请某资源时, 把该任务的优先级提升到可访问这个资源的所有任务中的最高优先级, 这个优先级称为该资源的优先级天花板。这种方法简单易行, 不必进行复杂的判断, 不管任务是否阻塞了高优先级任务的运行, 只要任务访问共享资源都会提升任务的优先级。
优先级继承是当任务A 申请共享资源S 时, 如果S正在被任务C 使用,通过比较任务C 与自身的优先级,如发现任务C 的优先级小于自身的优先级, 则将任务C的优先级提升到自身的优先级, 任务C 释放资源S 后,再恢复任务C 的原优先级。这种方法只在占有资源的低优先级任务阻塞了高优先级任务时才动态的改变任务的优先级,如果过程较复杂, 则需要进行判断。
notes:挂起状态和就绪状态是两个不同的状态。最主要的区别是看任务是否在内存中。挂起后,任务将被暂时调出内存;就绪时,是调入内存。
本篇介绍的是进入中断和退出中断函数:(注释很详细)
/*$PAGE*/
/*
*********************************************************************************************************
*                                              ENTER ISR
*                                               进入中断(执行中断)
* Description: This function is used to notify uC/OS-II that you are about to service an interrupt
*              service routine (ISR).  This allows uC/OS-II to keep track of interrupt nesting and thus
*              only perform rescheduling at the last nested ISR.该功能用来通知uc/os-II,正在进行一个中断服务。该功能可以使uc/os-II追踪中断嵌套信息并且只能在最后嵌套中断
*
* Arguments  : none
*
* Returns    : none
*
* Notes      : 1) This function should be called ith interrupts already disabled在任务级不能调用该函数
*              2) Your ISR can directly increment OSIntNesting without calling this function because
*                 OSIntNesting has been declared 'global'.如果系统使用的处理器能够执行自动的独立执行读取-修改-写入的操作,那么就可以直接递增265 * 中断嵌套层数(OSIntNesting),这样可以避免调用函数所带来的额外开销。在中断服务子程序中266 * 给OSIntNesting加1是不会有问题的,因为给OSIntNesting加1时,中断是关闭的
*              3) You MUST still call OSIntExit() even though you increment OSIntNesting directly.必须要有OSIntNesting()函数
*              4) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
*                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
*                 end of the ISR.      --  OSIntEnter()和OSIntExit()成对出现
*              5) You are allowed to nest interrupts up to 255 levels deep.中断深度可达255
*              6) I removed the OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() around the increment because
*                 OSIntEnter() is always called with interrupts disabled.
*********************************************************************************************************
*/void  OSIntEnter(void)
{if (OSRunning == OS_TRUE) {if (OSIntNesting < 255u) {              /*如果中断层次<255*/OSIntNesting++;                      /* Increment ISR nesting level 增加中断嵌套层次                       */}}
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                               EXIT ISR
*                                               退出中断(中断完成)
* Description: This function is used to notify uC/OS-II that you have completed serviving an ISR.  When
*              the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether
*              a new, high-priority task, is ready to run.
*               该功能用来通知uc/os-II已完成中断。当最后一个中断嵌套完成时,uc/os-II将调用调度程序确定是否有个新的高优先级的任务准备运行
* Arguments  : none
*
* Returns    : none
*
* Notes      : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
*                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
*                 end of the ISR.OSIntEnter()和OSIntExit()配套使用
*              2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock()) 给调度器上锁用于禁止任务调度 (查看 OSSchedLock()函数)
*********************************************************************************************************
*/void  OSIntExit(void)
{
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register为CPU状态寄存器分配存储空间 */OS_CPU_SR  cpu_sr = 0u;
#endifif (OSRunning == OS_TRUE) {                         /*如果操作系统还在运行,关闭中断*/OS_ENTER_CRITICAL();if (OSIntNesting > 0u) {                           /* Prevent OSIntNesting from wrapping 如果嵌套>0层,嵌套层减1      */OSIntNesting--;}if (OSIntNesting == 0u) {                          /* Reschedule only if all ISRs complete ...所有的中断都完成了 */if (OSLockNesting == 0u) {                     /* ... and not locked.并且嵌套锁也没有了,即已经完全解锁*/OS_SchedNew();                                /*进行新一轮的调用*/OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];/*在任务优先级表中找到最高优先级任务*/if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy检查具有最高优先级别的就绪任务的优先级是否是正在运行的任务的优先级。如果是,不用进行上下文切换*/
#if OS_TASK_PROFILE_EN > 0u                                  /*如果不是*/OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task 进行上下文切换 */
#endifOSCtxSwCtr++;                          /* Keep track of the number of ctx switches上下文切换的次数(统计任务计数器) */OSIntCtxSw();                          /* Perform interrupt level ctx switch 做中断任务切换      */}}}OS_EXIT_CRITICAL();                                    /*打开中断*/}
}

从上面的代码也可以看出来:进入中断函数很简单,就是将中断嵌套层数加1;退出中断函数相对复杂,涉及到了上下文切换及相关的判断。

OS_CORE.C(6)相关推荐

  1. OS_CORE.C(11)

    OS_SchedNew(void)找到将要运行的最高优先级任务函数 和任务调度函数OS_Sched(void): /* **************************************** ...

  2. OS_CORE.C(10)

    今天看os_core.c文件中的各种初始化函数. OS_EventWaitListInit(OS_EVENT *pevent)初始化事件控制块的等待列表: /*$PAGE*/ /*2018/2/8 * ...

  3. OS_CORE.C(总结)

    在内核的功能模块中,重点函数为: static  void  OS_InitEventList(void);/*初始化事件列表*/ static  void  OS_InitMisc(void);/* ...

  4. OS_CORE.C(1)

    第一个函数(获得信号量.互斥量.邮箱或者队列名字的函数)的流程图和分析图如下所示: /*$PAGE*/ /* ********************************************* ...

  5. OS_CORE.C(9)

    本篇介绍以下几个函数: OSVersion()获得版本号函数. OS_Dummy()虚拟函数. OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U ...

  6. OS_CORE.C(8)

    本篇介绍的是OSStart()函数和OSStatInit()函数和OSTimeTick()函数. OSStart()多任务开始函数: /*$PAGE*/ /* ******************** ...

  7. OS_CORE.C(5)

    /*$PAGE*/ /* *************************************************************************************** ...

  8. OS_CORE.C(3)

    OSTCBCur->OSTCBStat |= events_stat | /* Resource not available, ...无法获得资源的话就将其挂起 */OS_STAT_MULTI; ...

  9. OS_CORE.C(7)

    本篇介绍的是调度器的上锁和解锁: 调度器上锁函数OSSchedlock()的功能是用于禁止任务调度,使任务保持对CPU的控制权. 调度器开锁函数OSSchedUnlock()的功能是解除对任务调度的禁 ...

最新文章

  1. java 接口的访问权限_证明接口interface中定义的方法的访问权限为public
  2. SQL语言基础:SQL授权相关知识笔记​
  3. 分成互质组 (信息学奥赛一本通-T1221)
  4. 慎用mutableCopy
  5. OCA读书笔记(11) - 实现Oracle数据库审计
  6. C 语言:我不是针对谁,我是说在座的都是乐色
  7. Photoshop 入门教程「9」如何增加画布的空间?
  8. 用C语言能编程工控机吗,工控机、PLC、单片机的区别 工控机应用于哪些领域
  9. 数据挖掘思维和实战20 Apriori 与 FP-Growth:不得不再说一遍啤酒与尿布的故事
  10. mysql上机心得体会_数据库原理上机心得体会
  11. 微信小程序-更换头像
  12. 二维数组在c语言中的作用,C语言中的二维数组
  13. 分水岭matlab仿真,正确使用Matlab分水岭算法对细胞进行分割
  14. 《计算机网络—自顶向下方法》 第四章Wireshark实验:IP
  15. 点云配准之NDT算法
  16. java计算机毕业设计红色景点自驾游网站管理系统MyBatis+系统+LW文档+源码+调试部署
  17. MySql连接不上问题
  18. 微信小程序开发入门篇(一)
  19. 2013新春奉送 Android摄像头开发完美demo--- 循环聚焦 缩放大小 旋转picture 查询支持的pict
  20. ORB_SLAM2 KITTI数据集测试

热门文章

  1. 《Adobe After Effects CS6中文版经典教程》——1.3 创建合成图像与组织图层
  2. crackme算法分析---CRC32算法的妙用
  3. 当yum 遇到No more mirrors to try
  4. 硬核!尽量避免 BUG 手法
  5. 技术人, 请不要封闭自己
  6. 如何使用 Redis 实现大规模的帖子浏览计数
  7. 电商那些年,我摸爬打滚出的高并发架构实战精髓(续)
  8. 多线程:Vector是线程安全的吗
  9. TCP核心概念-慢启动,ssthresh,拥塞避免,公平性的真实含义
  10. Java “Resource leak: ‘scanner‘ is never closed“警告的解决办法