探索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文件。

函数说明

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

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

使用详解

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


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

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

 

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

其实现方式如下

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

使用区别

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

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

比如对于下面类似的代码


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

目录
相关文章
|
Web App开发 JavaScript 前端开发
使用vue快速开发一个带弹窗的Chrome插件
使用vue快速开发一个带弹窗的Chrome插件
607 0
使用vue快速开发一个带弹窗的Chrome插件
|
SQL
SQL Server判断某个字段是否包含中文/英文字符/数字
原文:SQL Server判断某个字段是否包含中文/英文字符/数字 因最近在清理系统中的脏数据,需要查询某个字段是否包含中文/英文字符/数字的数据, 比较简单,仅以此篇博客做一个简单总结,方便以后查阅。
5057 0
|
Ubuntu 安全 Docker
【DevOps】Docker 最佳实践指南(绝对干货)
祝您的 Docker 之旅一切顺利!
563 4
|
存储 算法 Linux
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
735 0
|
算法 物联网 异构计算
基于FPGA的4FSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的4FSK调制解调系统的Verilog实现,包括高斯信道模块和误码率统计模块,支持不同SNR设置。系统在Vivado 2019.2上开发,展示了在不同SNR条件下的仿真结果。4FSK调制通过将输入数据转换为四个不同频率的信号来提高频带利用率和抗干扰能力,适用于无线通信和数据传输领域。文中还提供了核心Verilog代码,详细描述了调制、加噪声、解调及误码率计算的过程。
457 11
|
JavaScript 前端开发 开发者
决战前端之巅!Element UI与Vuetify谁才是Vue.js组件界的霸主?一场关于颜值与实力的较量!
【8月更文挑战第30天】本文对比了两款热门的Vue.js组件库——Element UI与Vuetify。Element UI由饿了么团队打造,提供多种高质量UI组件,设计简洁大方。Vuetify基于Material Design规范,支持Vue.js 2.0及3.0版本,具备前瞻性。两者均涵盖表单、导航、数据展示等组件,Element UI配置选项丰富,而Vuetify则提供了更深层的样式定制功能。开发者可根据项目需求及个人偏好选择合适的组件库。
1245 0
|
机器学习/深度学习 人工智能 资源调度
【博士每天一篇文献-算法】连续学习算法之HAT: Overcoming catastrophic forgetting with hard attention to the task
本文介绍了一种名为Hard Attention to the Task (HAT)的连续学习算法,通过学习几乎二值的注意力向量来克服灾难性遗忘问题,同时不影响当前任务的学习,并通过实验验证了其在减少遗忘方面的有效性。
381 12
|
机器学习/深度学习 并行计算 PyTorch
GPU 加速与 PyTorch:最大化硬件性能提升训练速度
【8月更文第29天】GPU(图形处理单元)因其并行计算能力而成为深度学习领域的重要组成部分。本文将介绍如何利用PyTorch来高效地利用GPU进行深度学习模型的训练,从而最大化训练速度。我们将讨论如何配置环境、选择合适的硬件、编写高效的代码以及利用高级特性来提高性能。
2261 1
|
安全 Linux 开发者
如何根据自己的开发板型号下载和配置交叉编译链
【8月更文挑战第25天】本指南详细介绍了如何为您的开发板下载和配置合适的交叉编译链。首先,需确定开发板的型号及其处理器架构(如ARM、MIPS等)。接着,可通过官方渠道或开源社区寻找适用的交叉编译链。下载时,请确保版本与开发板匹配并验证来源可靠性。配置过程包括解压文件、设置环境变量及验证配置正确性。最后,通过编译并运行简单的测试程序(如“Hello, World!”)来测试交叉编译链的有效性。若过程中遇到困难,建议查阅相关文档或求助于技术论坛。
360 1
|
敏捷开发 Web App开发 jenkins
自动化测试框架的搭建与实践
【8月更文挑战第3天】在软件开发过程中,自动化测试已成为提高软件质量和开发效率的关键。本文将深入讨论如何搭建一个高效且可靠的自动化测试框架,包括工具选择、环境配置、脚本编写和执行策略等。通过实际案例,我们将展示框架的具体实施过程,并分析其在真实项目中的表现和效益。
272 1