一. 基本问题
 
FreeRTOS会在关键区即taskENTER_CRITICAL()和taskEXIT_CRITICAL()包裹的区间中,执行进程切换。即在关闭中断的时候,进行进程切换。
我们已经知道,即便关闭中断,PowerPC的sc中断,还是可以得到响应。但是时钟中断呢?这是个外部中断,无法得到响应。
那么是何时打开的中断呢?新进程切入之后,立即打开中断?在多个TASK级别做开关中断配对?
 
1.关键区和关键资源
 
或者叫竞争区间,使用PV原语保护,操作系统基本概念。在FreeRTOS中,为使用taskENTER_CRITICAL()和taskEXIT_CRITICAL()包裹的区间。
关键区中使用即PV原语保护的资源为关键资源。
 
2.基本同步机制:开关中断
 
单核CPU存在两个并行流程:TASK和中断ISR。中断可以打断TASK的执行。所以TASK中的关键区间需要使用开关中断保护,而中断ISR就不需要再关中断了。这是最基本的同步机制。
如果中断存在优先级,高优先级中断可以打断低优先级中断,则存在三个并行流程:TASK、低优先级中断ISR和高优先级中断ISR。如此仅仅关闭中断,已经无法起到保护关键区的作用。需要把CPU的当前中断响应级别提升到关键区间所需要的最高级别。这里的所需要,是指会使用到被保护资源的最高优先级的中断的优先级。即便不是最高,但其上优先级的中断ISR不使用被保护资源,则不会导致死锁。
多核CPU除了考虑本核的同步外,还需要考虑与其他核的同步,需要使用系统级别的标志。因为多个核共享同一个内存空间,所以这个同步标志,可以是一个存在内存中的变量。
 
3.关键区尽量短
 
关闭中断,会使CPU无法及时响应外部中断。所以为了提高响应的实时性,需要使关键区间尽量短。也就是关闭中断的时间尽量短。不涉及关键资源的操作,尽量放在关键区间之外执行。
 
4.PV操作成对出现,降低复杂度
 
为了降低程序的复杂度。使同步操作更易阅读理解,同时降低出错的概率。PV操作一般成对出现,并且出现在同一个函数中。为了保证成对出现,甚至可以使用goto语句。即使用if判断到需要直接退出的例外情况时,不是直接在if中开中断然后退出,而是使用goto跳转到成对的唯一一个开中断操作。
 
5.关键区间中切换进程提升了复杂度
 
所以关键区间中,在关闭中断的状态下切换进程,提升了代码的复杂度。如何保证开关中断的动作成对出现,变成了一个很复杂的问题。
下面我们跟踪xSemaphoreGive/xSemaphoreTake的流程,来看何时打开的中断。
 
二.Semaphore
 
Semaphore的使用队列实现。xSemaphore的Give和Task分别向队列中存和从队列中取。
 
1.xSemaphoreGive
 
进入关键区之后,如果队列不为空,则立即切换进程。从注释可以看出,这里有两种实现:a.立即切换进程;b.这里只记录状态,在退出关键区时执行切换。这个跟port的实现有关,跟FreeRTOS无关。
 
另外,这里也不一定会切换进程,跟进程的优先级有关。如果等待信号量的进程优先级比当前进程优先级低,则不会进行切换。这里我们假设会切换。
 
2.xSemaphoreTake
如果队列为空则在箭头处睡眠等待。同时,队列被存入元素后,也是在这里被唤醒。唤醒后,执行如下代码检查队列是否为空:
可以看到,这里又重新执行了一次taskENTER_CRITICAL(),取得队列元素之后,退出时又执行了一次taskEXIT_CRITICAL(),这是成对的操作。所以不存在被切入的进程打开进程切换前关闭的中断的情况。
问题没有解决:中断时何时被打开的?
 
三.中断嵌套实现
 
FreeRTOS自带的例子中,有两种实现。
 
1.自定义嵌套层级变量
 
2.使用TCB中的嵌套层级变量
 
即直接使用FreeRTOS的vTaskEnterCritical/vTaskExitCritical,这两个函数:
 
两个的区别在于一个使用全局变量,一个使用每TASK变量存储中断嵌套层级。
为什么每一个TASK一个中断嵌套层级呢?
 
四.谁的中断嵌套层级
按常规的理解,中断属于CPU,而不属于TASK,一个CPU上可以有多个TASK在执行。而CPU是全局的,所以中断状态也应该是全局的,所以中断嵌套层级也应该使用全局变量存储。
 
每个TASK一个中断嵌套层级,如何理解?
 
我们知道每个TASK记录自己的各个寄存器的值,是可以理解的。以便切入时恢复之前的状态。难道每个TASK也维护执行时中断状态,以便切入时恢复执行?难道每个TASK也记录中断的开关状态,切入时恢复之前的中断开关状态?
 
看一下TASK切换时保存和恢复的寄存器,以PowerPC为例。
 
五.中断发生时保存和恢复的寄存器状态
 
 
SRR1中保存着中断发生前的MSR寄存器的值,也包括EE位。那么恢复时,自然也会恢复EE位。
 
六.总结
 
首先回答何时打开中断的问题:进程切入时,即恢复进程切出前的中断开关状态。
另外一个结论:中断状态在物理上虽然是全局的,但在软件上是每个TASK维护一份。
PS. 复杂度还是提升了,OS层需要加倍小心,好在APP层无需过多考虑。

FreeRTOS-为什么关中断之后切换进程?的更多相关文章

  1. windbg-.process切换进程(内核)

    .process .process 命令指定要用作进程上下文的进程(Set Process Context) .process显示当前进程的EPROCESS,这里显示当前进程为test.exe kd& ...

  2. 编写一个stm32 svc关中断函数

    做到了让stm32触发svc中断并传递进去参数然后切换到handler模式并修改特殊寄存器的值,从而达到关中断,但是其实这个程序直接就是特权级,故不进入handler模式也可以修改特殊寄存器..... ...

  3. 结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程

    结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程 目录 结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程 一. 实验准备 二. 实验过程 I 分析中断上下文的切换 ...

  4. 未关中断情况下的hardlock

    最近遇到一例crash,3.10内核,hardlock,查看对应的堆栈,中断是使能的. 查看对应的hrtimer_interrupts和hrtimer_interrupt_save的值,发现确实相等. ...

  5. linux的可中断sleep_on函数分析

    void interruptible_sleep_on (struct task_struct **p)// **p是个全局变量 { struct task_struct *tmp; if (!p)# ...

  6. (笔记)Linux内核学习(一)之内核介绍

    内核与操作系统: 内核是操作系统的核心部分,包含了系统运行的核心过程,决定系统的性能,操作系统启动内核被装入到RAM中: 操作系统与底层硬件设备交互和为运行应用程序提供执行环境. Linux内核与微内 ...

  7. 13 . Python3之并发编程

    什么是操作系统? 为什么要有操作系统? 现代的计算机系统主要是由一个或者多个处理器,主存,硬盘,键盘,鼠标,显示器,打印机,网络接口及其他输入输出设备组成. 一般而言,现代计算机系统是一个复杂的系统. ...

  8. 译<容器网络中OVS-DPDK的性能>

    译<容器网络中OVS-DPDK的性能> 本文来自对Performance of OVS-DPDK in Container Networks的翻译. 概要--网络功能虚拟化(Network ...

  9. FreeRTOS 临界段和开关中断

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 临界段代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断.为确保临界段代码的执行不被中断 ...

随机推荐

  1. Android中限制输入框最大输入长度

    通常情况下只需要在布局文件中加入maxlength这一属性即可 <EditText android:inputType="text" android:singleLine=& ...

  2. 【FPGA篇章一】FPGA工作原理:详细介绍FPGA实现编程逻辑的机理

    欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 FPGA(Field Programmable Gate Array),即现场可编程逻辑门阵列,它是作为专用集成电路(ASIC)领域中一种半 ...

  3. 【Scala】Actor并发编程实现单机版wordCount

    文章目录 对单个文本文件进行单词计数 对多个文本文件进行单词计数 对单个文本文件进行单词计数 import scala.actors.Actor import scala.io.Source //读取 ...

  4. Day_14【IO流】扩展案例1_缓冲区字符输入、输出流,键盘录入,contains()方法的统一运用

    分析以下需求,并用代码实现 实现一个验证码小程序,要求如下: 1. 在项目根目录下新建一个文件:data.txt,键盘录入3个字符串验证码,并存入data.txt中,要求一个验证码占一行: 2. 键盘 ...

  5. 【Hadoop离线基础总结】MapReduce案例之自定义groupingComparator

    MapReduce案例之自定义groupingComparator 求取Top 1的数据 需求 求出每一个订单中成交金额最大的一笔交易 订单id 商品id 成交金额 Order_0000005 Pdt ...

  6. jbpm4.4 timer的使用

    今天学习了jbpm4 的timer使用,一直测试都不成功:配置如下: <?xml version="1.0" encoding="UTF-8"?> ...

  7. css中文字两端对齐兼容IE

    text-align: justify; text-justify:inter-ideograph;

  8. ionic + asp.net core webapi + keycloak实现前后端用户认证和自动生成客户端代码

    概述 本文使用ionic/angular开发网页前台,asp.net core webapi开发restful service,使用keycloak保护前台页面和后台服务,并且利用open api自动 ...

  9. Python PIL Image图片显示系列

    1. PIL Image图片显示 在使用PIL函数中的Image方法读取图片时,对于图片的shape,可能有不少宝宝存在疑惑.是什么疑惑了?就是image = Image.open(image_pat ...

  10. 洛谷 p1605 迷宫问题 详解

    题解:dfs搜索 #include <iostream> #include <algorithm> #include <cstring> #include < ...