探索ucos-ii之路--(二)临界区

临界区概述

和其它内核一样,μC/OS-Ⅱ为了处理临界段代码需要关中断,处理完毕后再开中断。这使得μC/OS-Ⅱ能够避免同时有其它任务或中断服务进入临界段代码。关中断的时间是实时内核开发商应提供的最重要的指标之一,因为这个指标影响用户系统对实时事件的响应性。μC/OS-Ⅱ努力使关中断时间降至最短,但就使用μC/OS-Ⅱ而言,关中断的时间很大程度上取决于微处理器的架构以及编译器所生成的代码质量。

微处理器一般都有关中断/开中断指令,用户使用的C语言编译器必须有某种机制能够在C中直接实现关中断/开中断地操作。某些C编译器允许在用户的C源代码中插入汇编语言的语句。这使得插入微处理器指令来关中断/开中断很容易实现。而有的编译器把从C语言中关中断/开中断放在语言的扩展部分。μC/OS-Ⅱ定义两个宏(macros)来关中断和开中断,以便避开不同C编译器厂商选择不同的方法来处理关中断和开中断。μC/OS-Ⅱ中的这两个宏调用分别是:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。因为这两个宏的定义取决于所用的微处理器,故在文件OS_CPU.H中可以找到相应宏定义。每种微处理器都有自己的OS_CPU.H文件。

函数说明

[cpp] view plain copy print?

  1. *********************************************************************************  
  2. *  
  3. *   函数名 :   OS_ENTER_CRITICAL( )  asm {PUSHF; CLI}              
  4. *   描述  :   Disable interrupts, 用于代码进入临界区时关闭中断  
  5. *   实现  :   os_cpu.h中 -=> #define OS_ENTER_CRITICAL()  asm {PUSHF; CLI}            
  6. *  
  7. *********************************************************************************  
  8. *  
  9. *   函数名 :   OS_EXIT_CRITICAL( )  
  10. *   描述  :   Enable  interrupts, 用于代码离开临界区时开启中断  
  11. *   实现  :   os_cpu.h中 -=> #define  OS_EXIT_CRITICAL()   asm  POPE  
  12. *  
  13. *********************************************************************************  
*********************************************************************************
*
*	函数名	:	OS_ENTER_CRITICAL( )  asm {PUSHF; CLI}
*	描述	:	Disable interrupts, 用于代码进入临界区时关闭中断
*	实现	:	os_cpu.h中 -=> #define OS_ENTER_CRITICAL()  asm {PUSHF; CLI}
*
*********************************************************************************
*
*	函数名 :	OS_EXIT_CRITICAL( )
*	描述	:	Enable  interrupts, 用于代码离开临界区时开启中断
*	实现	:	os_cpu.h中 -=> #define  OS_EXIT_CRITICAL()   asm  POPE
*
*********************************************************************************

OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()通常用来保护应用程序中的临界代码;
然而要特别小心,如果在调用一些如OSTimeDel()之类的功能函数之前关中断,应用程序将会死机;
原因是任务被挂起一段时间,直到挂起时间到,但由于中断关掉了,
时钟节拍中断一直得不到服务,显然所有的挂起类调用都有这样的问题,所以要特别小心。

作为一条普遍适用的规则,调用UCOS-ii功能函数时,中断总是开着的。
并且我们自己应用程序中中断关闭的时间应该尽可能的短, 
避免系统关中断时间太长可能会引起中断丢失。

使用详解

使用详解, 比如说我们的某个任务在执行过程中需要访问并且修改某个全局变量,
而如果系统中也有其他任务要访问这个变量, 这时候修改可能会被其他程序的访问造成一些影响 
那么这时候访问这个全局变量的代码就是临界区, 我们在操作时就需要开关中断

[cpp] view plain copy print?

  1. void Task(void *pdata)  
  2. {  
  3.     OS_ENTER_CRITICAL(); //关闭中断  
  4.   
  5.     访问并且修改全局变量  // uCOS II 临界代码段  
  6.   
  7.     OS_EXIT_CRITICAL(); //打开中断  
  8. }  
void Task(void *pdata)
{
    OS_ENTER_CRITICAL(); //关闭中断

	访问并且修改全局变量	// uCOS II 临界代码段

    OS_EXIT_CRITICAL(); //打开中断
}

宏OS_ENTER_CRITICAL ( ) 和 OS_EXIT_CRITICAL ( ) 的三种实现方法:

 

在UCOS2的源代码及相关应用程序中,总会出现往往通过OS_CRITICAL_METHOD宏来使用和实现不同的开关中断代码宏,

其实现方式如下

[cpp] view plain copy print?

  1. /*  
  2. ********************************************************************************************************* 
  3. *                              Intel 80x86 (Real-Mode, Large Model) 
  4. * Method #1:  Disable/Enable interrupts using simple instructions.  After critical section, interrupts 
  5. *             will be enabled even if they were disabled before entering the critical section. 
  6. * Method #2:  Disable/Enable interrupts by preserving the state of interrupts.  In other words, if  
  7. *             interrupts were disabled before entering the critical section, they will be disabled when 
  8. *             leaving the critical section. 
  9. * Method #3:  Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you 
  10. *             would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then 
  11. *             disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to  
  12. *             disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr' 
  13. *             into the CPU's status register. 
  14. ********************************************************************************************************* 
  15. */  
  16. // Method #1:  
  17. #ifdef  OS_CRITICAL_METHOD  1  
  18. #  
  19. #define OS_ENTER_CRITICAL() __asm__ { "CLI" }  
  20. #define OS_EXIT_CRITICAL()  __asm__ { "STI" }     
  21. #  
  22. #endif    
  23.   
  24. // Method #2  
  25. #ifdef  OS_CRITICAL_METHOD  2  
  26. #  
  27. #define OS_ENTER_CRITICAL() __asm__ { "PUSHF\n\tCLI" }  
  28. #define OS_EXIT_CRITICAL()  __asm__ { "POPF" }    
  29. #  
  30. #endif  
  31.   
  32. // Method #3  
  33. #ifdef OS_CRITICAL_METHOD   3  
  34. #  
  35. #define OS_ENTER_CRITICAL() { cpu_str = OSCPUSaveSR( ) }  
  36. #define OS_EXIT_CRITICAL()  { OSCPURestoreSR(cpu_str) }  
  37. #  
  38. #endif  
/*
*********************************************************************************************************
*                              Intel 80x86 (Real-Mode, Large Model)
*
* Method #1:  Disable/Enable interrupts using simple instructions.  After critical section, interrupts
*             will be enabled even if they were disabled before entering the critical section.
*
* Method #2:  Disable/Enable interrupts by preserving the state of interrupts.  In other words, if
*             interrupts were disabled before entering the critical section, they will be disabled when
*             leaving the critical section.
*
* Method #3:  Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
*             would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
*             disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
*             disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
*             into the CPU's status register.
*********************************************************************************************************
*/
// Method #1:
#ifdef	OS_CRITICAL_METHOD	1
#
#define	OS_ENTER_CRITICAL()	__asm__ { "CLI" }
#define OS_EXIT_CRITICAL()	__asm__ { "STI" }
#
#endif	

// Method #2
#ifdef	OS_CRITICAL_METHOD	2
#
#define	OS_ENTER_CRITICAL()	__asm__ { "PUSHF\n\tCLI" }
#define OS_EXIT_CRITICAL()	__asm__ { "POPF" }
#
#endif

// Method #3
#ifdef OS_CRITICAL_METHOD	3
#
#define	OS_ENTER_CRITICAL()	{ cpu_str = OSCPUSaveSR( ) }
#define OS_EXIT_CRITICAL()	{ OSCPURestoreSR(cpu_str) }
#
#endif

使用区别

 第一种方式,OS_ENTER_CRITICAL()简单地关中断,OS_EXIT_CRITICAL()简单地开中断。这种方式虽然简单高效,但无法满足嵌套的情况。如果有两层临界区保护,在退出内层临界区时就会开中断,使外层的临界区也失去保护。虽然ucos的内核写的足够好,没有明显嵌套临界区的情况,但谁也无法保证一定没有,无法保证今后没有,无法保证在附加的驱动或什么位置没有,所以基本上第一种方法是没有人用的。

   第二种方式,OS_ENTER_CRITICAL()会在关中断前保存之前的标志寄存器内容到堆栈中,OS_EXIT_CRITICAL()从堆栈中恢复之前保存的状态。这样就允许了临界区嵌套的情况。但现在看来,这种方法还存在很大的问题,甚至会出现致命的漏洞。

比如对于下面类似的代码

转载:http://blog.csdn.net/gatieme/article/details/21369629

时间: 2024-10-26 21:20:58

探索ucos-ii之路--(二)临界区的相关文章

探索Oracle之数据库升级二 11.2.0.3升级到11.2.0.4完整步骤

探索Oracle之数据库升级二  11.2.0.3升级到11.2.0.4完整步骤   说明:         这篇文章主要是记录下单实例环境下Oracle 11.2.0.1升级到11.2.0.3的过程,当然RAC的升级是会有所不同.但是他们每个版本之间升级步骤都是差不多的,先升级Database Software,再升级Oracle Instance.  Oracle 11.2.0.4的Patchset No:19852360下载需要有Oracle Support才可以.  Patchset包含

我的VSTO之路(二):VSTO程序基本知识

原文:我的VSTO之路(二):VSTO程序基本知识 开始之前,首先我介绍一下我的开发环境:VS2010 + Office 2010,是基于.Net framework 4.0和VSTO 4.0.以下的范例代码都基于这个,如果你使用的是VS2008,那么问题也不大,基本可以移植过去.需要注意的是.Net framework 4.0中增加了dynamic类型和可选参数,而这两点新的特性在VSTO 4.0中被广泛使用,新特性的详细内容我就不介绍了,(其实介绍的地方很多,Google一下就可以了),移植

stm32f207移植ucos ii系统,并口中断配置问题

问题描述 stm32f207移植ucos ii系统,并口中断配置问题 stm32f207并口与DP主站通信,移植ucos ii系统时,bsp里的并口中断配置要怎么做,并且要用一个宏来选择是8位还是16位,请高手来帮帮我

uCOS/ii 学习心得及体会

1.首先发布 任哲的<嵌入式实时操作系统uCOS-II原理及应用>        这本书非常适合初学者学习 uCOS-ii       2.   请问:空闲任务和统计任务是否建立任务控制块呢?             任务块链表中是否存在空闲任务和统计任务的任务控制块呢?如果没有的话,操作系统如何调度呢?         标准答案:             在uCOS/ii内核中,调用OSInit()函数中会首先创建空闲任务,同时当用户"允许"统计任务时,也会接着创建统计任

东航试水电商网站继续探索东航转型之路

摘要: 大张旗鼓试水电商网站之后,东航并未止步.近日,东航又在沪成立东方航空 电子商务 有限公司(下称东航电商),继续探索东航转型之路. 东航现任掌门人刘绍勇领导下的东航一直想 大张旗鼓试水电商网站之后,东航并未止步.近日,东航又在沪成立东方航空 电子商务 有限公司(下称"东航电商"),继续探索东航转型之路. 东航现任掌门人刘绍勇领导下的东航一直想摆脱航空业仅仅是"卖机票"的业务模式,而希望从"传统航空承运人"向"现代航空服务集成商&q

e租宝承办金融论坛 探索P2P发展之路

10月30日,蚌埠市首届互联网金融发展论坛盛大召开,承办方e租宝不仅邀请了众多学者专家,还邀请了蚌埠市央行及政府多机构相关负责人.论坛以"理性与规范 机遇与创新"为主题,针对当前http://www.aliyun.com/zixun/aggregation/1964.html">中国互联网金融发展最为迅猛的P2P行业如何摆脱野蛮式发展进行了深入的探讨. 众所周知,随着我国进入互联网金融时代,越来越多的P2P平台出现在公众视野中, P2P网贷平台依托互联网的创新技术,让民

九城生死路(二)危急关头的开源节流

上图简要的显示了九城关于07年第四季度到08年第四季度的财政收入变化.虽然魔兽世界在中国大陆运营之路坎坷不平,但这并不影响九城在收入上稳步提高.直到网易夺得了魔兽世界的运营权,当季九城收入下滑,08年的净利润直接比预期值低了72%. 截止到7月14日,九城股价1年内的变动范围为:最高28.50美元/股,最低8.53美元/股.周一收盘价为8.65美元/股,周二在 纳斯达克,该股跌31美分,以8.34美元/股报收,盘后交易中再跌5美分至8.29美元/股.九城股价创过去52周新低. 从28.5跌到8.

浙江开创金融信息服务外包先河 探索IT外包之路

中新网杭州6月27日电(记者 夏毅 实习生 吴显)金融业信息服务外包正成为浙江经济发展的新亮点. 日前,浙江省经信委.浙江银监局等7个部门联合签署<关于推进浙江金融业信息服务外包合作备忘录>,共同推进浙江省金融业信息服务外包工作.同时,中国人寿浙江省分公司等保险机构还与浙江IT服务企业签署了具体的服务外包项目合作书. 浙江信息外包创全国先河 首涉金融行业 浙江信息服务外包领域借撬动金融业再获延伸,对此,浙江省经济和信息化委员会副主任邓国强认为,金融机构和浙江省软件.信息服务企业的广泛合作,加快

Groovy探索之MOP 十 Interceptor 二

在本系列的<Groovy探索之MOP 九 Interceptor 一>中,我们已经详细的介绍了一个简单的拦截器类的方方面面,使得我们初步有了拦截器的基础.本篇需要在前面的拦截器类的基础上,进一步用拦截器类来实现我们的AOP编程. 首先,我们在本系列的第一篇中,所拦截的方法都是固定的方法.现在,我们需要把它扩展成由拦截器类的使用者来指定被拦截的方法. 先还是给出需要被拦截的类来: class Foo { def test1() { println 'test1' } def test2() {