一. 基本问题
 
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. 【Spark】如何用Spark查询IP地址?

    文章目录 需求 思路 ip地址转换为Long类型的两种方法 ip地址转换数字地址的原理 第一种方法 第二种方法 步骤 一.在mysql创建数据库表 二.开发代码 需求 日常生活中,当我们打开地图时,会 ...

  2. 就没有我遇不到的报错!java.lang.NoClassDefFoundError: org/apache/hadoop/hbase/filter/Filter

    本来准备用HBase的Bulkload将HDFS的HFile文件导入到HBase的myuser2表中,用的是yarn jar的命令 yarn jar /export/servers/hbase-1.2 ...

  3. Day_11【集合】扩展案例5_对list集合对象中的元素进行反转,求最大值最小值,求元素i在list集合中首次出现的索引,将oldvalue替换为newvalue

    分析以下需求,并用代码实现 定义MyArrays工具类,该工具类中有以下方法,方法描述如下: 1.public static void reverse(ArrayList<Integer> ...

  4. 第三家面试过程,及导出elcel的进一步小结。(8月11号 周五)

    今天收到第三家公司的面试通知,面试地址也在民治附近,面试时间是上午十点.今早又失眠了,感觉到这边这么几天,总是天天失眠,晚上睡不好白天瞌睡睡不着,估计还需要些许时间的适应,早上七点多我整理好面试需要准 ...

  5. Linux 通过终端命令行切换系统语言

    通过命令的形式修改系统的语言,比较详细的讲解了来龙去脉: 文章目录 0 前言 1 locale 文件 2 查找相关文件 3 解决方案 4 相关信息 4.1 locale属性的含义 4.2 LANGUA ...

  6. 设计模式之GOF23组合模式

    组合模式Composite 使用组合模式的场景:把部分和整体的关系用树形结构表示,从而使客户端可以使用统一的方式处理对象和整体对象(文件和文件夹) 组合模式核心: -抽象构件(Component)角色 ...

  7. 利用python在微信群中签到、抢沙发(适用于任何账号)

    利用python在微信群中签到.抢沙发 注意 程序仅能在电脑上运行,运行时需要保证群界面在最前端且不被移动. 背景 我是一名高中生(2020年),疫情期间,在家上网课,有的老师让我们在班群里签到. 其 ...

  8. js 延迟加载的几种方法

    1. defer 属性HTML 4.01 为 <script>标签定义了 defer属性. 用途:表明脚本在执行时不会影响页面的构造.也就是说,脚本会被延迟到整个页面都解析完毕之后再执行. ...

  9. leetcode 第184场周赛第一题(数组中的字符串匹配)

    一.函数的运用 1,strstr(a,b); 判断b是否为a的子串,如果是,返回从b的开头开始到a的结尾 如“abcdefgh” “de” 返回“defgh”: 如果不是子串,返回NULL: 2,me ...

  10. Spark aggregateByKey函数

    aggregateByKey与aggregate类似,都是进行两次聚合,不同的是后者只对分区有效,前者对分区中key进一步细分 def aggregateByKey[U: ClassTag](zero ...