《多任务抢占式调度器》读书笔记

1、多任务系统

在多任务调度器的作用下,多个任务轮流使用cpu,实现多任务相互独立并发运行的效果,能够充分利用硬件资源,提高cpu效率

2、任务特性

a、动态性

运行态:任务处于占用cpu运行的状态,有且只能有一个处于运行态的任务

就绪态:可运行的任务,等待占用cpu的任务释放cpu

挂起态:由与某些条件不满足而不能运行的任务

b、独立性

任务之间相互独立,不存在相互调用的关系,使得任务在逻辑上是平等的,任务见的通信由规定的变量来传输

c、并发性

由同一cpu轮换运行多个任务,注意任务并不需要运行完了才能去运行其他任务

3、抢占式调度

在就绪态的任务中出现了优先级比当前任务优先级高的任务,便立即剥夺当前任务运行权,把cpu分配给优先级最高的任务,这样cpu总是在执行就绪条件下优先级最高的任务

4、多任务的时间基准

由一个定时器产生固定周期中断充当时间基准

5、任务的挂起与恢复

当高优先级任务需要给低优先级任务让道时,需要将高优先级任务挂起,通过OSDelay设置挂起时间拍数,在时间到来后将被挂起的高优先级再恢复为就绪

定时器中断服务函数中,依次给各个任务延时节拍数减一,一旦某个任务延时结束(节拍数减到0),就将它由挂起态变为就绪态

程序中可设置一始终处于就绪态的最低优先级空闲函数,保证其他函数挂起时cpu有事可做

6、可重入设计

当某一任务正在运行某个公共函数,接着被更高优先级的任务抢占,而这一任务恰好也要调用这一公共函数,那么就极有可能破坏前一个任务在这个函数的数据,因此我们采用可重入设计来规避这种情况

// 电赛延期,进度不能断,继续

可重入函数中所有变量都为局部变量,故在不同任务调用该函数时,对于同一局部变量所分配的存储空间并不相同,所以不会相互干扰

7、互斥调用

除了可重入设计以外,我们还可以采用互斥调用的方法来规避数据的互相破坏;临界资源是公共资源,但不具备被多个线程访问的特性,因此在多任务系统中,我们需要保证共享资源的互斥访问,要实现互斥访问,方法有在访问临界资源的程序(称为临界区)关中断、关调度、互斥信号量、计数信号量等,使得临界区程序执行时不被其他任务打断,使得该任务在访问临界资源时处于独占状态,因此也需要注意,临界区的代码要尽量短,否则将降低cpu响应性能

8、全局变量与局部变量

全局变量存储在公共的数据存储器里,局部变量存储在所属函数的私有栈里,栈,可以引申为客栈,即临时存放数据的地方,栈是一个线性的空间,可以用通过申请一个静态的数组,打造一个人工栈,注意栈的大小要合适

9、任务控制块Task Contrl Block(TCB)

每个任务都有一个任务控制块,用于记录任务执行的环境,一般为一结构体,作为任务与数据的桥梁,找到他就可以找到任务的所有资源,如此,我们的得到了任务的三个要件:程序代码、私有栈、任务控制块

图示:

 10、任务的切换

当任务1将cpu让给任务2时,首先,任务1需要做好自己的收尾工作,即将自己的现场数据——PC、寄存器值压入任务堆栈,SP指针存入任务控制块,同时,任务2做好交接工作,将任务堆栈中的PC、寄存器值从堆栈中取出来,将SP指针从任务控制块取出。故本质上,交接工作是取出SP指针,因为任务栈存的PC和寄存器值地址也存在SP指针里

 11、任务的创建

创建任务的函数OSTaskCreate()将接收三个参数:任务的入口地址、任务堆栈的首地址和任务的优先级,调用任务创建这一函数后,系统会根据用户给出的参数初始化任务私有栈,并将堆栈指针保存到任务控制块中,在任务就绪表中标记任务为就绪状态。

初始化后的任务私有栈保存着PC、LR以及寄存器值等,一般会按一定顺序,且PC排在易于访问的位置

多任务系统启动后,将运行OSStartHighRdy,这一函数会将第一个运行的任务的SP从TCB中取出,而后由SP依次将cpu的现场恢复,这是这个任务将占有cpu,直到其他任务抢占cpu;OSStartHighRdy只在启动伊始运行一次

12、实现抢占式调度

基于任务优先级的抢占式调度,也就是当最高优先级任务进入就绪状态时,立即抢占正在运行的低优先级任务的cpu资源,为保证cpu总是在执行优先级最高任务,我们需要在任务状态改变后就执行一次对当前执行任务是否为最高优先级任务的判断

任务状态会在什么时候改变呢,一是当高优先级任务因需要某种资源或延时,主动请求挂起,此时处于就绪状态的低优先级任务可以运行,称为任务级的切换;二是当高优先级任务因为时钟节拍的到来或中断处理结束后,内核发现更高优先级任务获得了执行权限(如延时的时钟到时),则在中断后直接切到更高优先级任务执行,这种调度称为中断级的切换

// insert:名词解释:IRQ:Interrupt ReQuest中断请求;ISR:Interrupt ServeR中断服务程序

任务级的切换详见10、11,下面讲讲中断级的切换

与STM32 HAL类似,系统也存在一个统管了系统所有中断的ASM_IRQHandler,用于中断的调度,同时也会指向C函数C_IRQHandler(),在其中判断中断类型,并跳转到对应的中断服务函数,执行服务函数的内容,执行完后,将推出中断,执行OSInitExit,但,根据中断嵌套的原则,并不会立即返回先前的任务,而是将嵌套层OSIntNesting减一(OSIntNesting在每次进入一层中断时都会加一),直到OSIntNesting为0时,表面所有的嵌套中断都完成了,这是会判断此时最高优先级任务是什么,并执行OSIntCtxSw准备任务切换

任务的切换准备工作通过OSIntCtxSw完成,它将此时任务的SP指针指向lr,注意此时指向的是中断返回地址,这时我们将里面的内容换成任务切换的函数OS_TASK_SW_INT地址,那么当中断返回时,我们实际上指向的是OS_TASK_SW_INT

接下来的切换与10中基本一致

13、任务的挂起与恢复

OSTaskSuspend函数可以将任务手动挂起,通过将任务从任务就绪表中移除,并重启任务调度实现这一功能

OSTaskResume可以将被挂起的任务恢复就绪态,进行任务调度

参考:《多任务抢占式调度器》by Lisuwei

2021/8/14   0:14

LynnSX in HRB

【RTOS】《多任务抢占式调度器》笔记的更多相关文章

  1. VxWorks实验六 基于优先级的抢占式调度及实验的源程序和实验步骤

    基于优先级的抢占式调度及实验的源程序和实验步骤 1 实验目的    1.学习并验证基于优先级的抢占式调度2 实验内容    在实验一建立的 project 中,创建3 个任务,对这三个任务使用基于优先 ...

  2. 循环引擎 greenlet 没有显式调度的微线程,换言之 协程

    小结: 1. micro-thread with no implicit scheduling; coroutines, in other words. 没有显式调度的微线程,换言之 协程 2. 一个 ...

  3. based on Greenlets (via Eventlet and Gevent) fork 孙子worker 比较 gevent不是异步 协程原理 占位符 placeholder (Future, Promise, Deferred) 循环引擎 greenlet 没有显式调度的微线程,换言之 协程

    gevent GitHub - gevent/gevent: Coroutine-based concurrency library for Python https://github.com/gev ...

  4. 深入理解Java虚拟机 第三章 垃圾收集器 笔记

    1.1   垃圾收集器 垃圾收集器是内存回收的具体实现.以下讨论的收集器是基于JDK1.7Update14之后的HotSpot虚拟机.这个虚拟机包含的所有收集器有: 上图展示了7种作用于不同分代的收集 ...

  5. 《Python cookbook》 “定义一个属性可由用户修改的装饰器” 笔记

    看<Python cookbook>的时候,第9.5部分,"定义一个属性可由用户修改的装饰器",有个装饰器理解起来花了一些时间,做个笔记免得二刷这本书的时候忘了 完整代 ...

  6. k8s-调度器、预选策略及优选函数-二十

    一.简介 master上运行着三个最核心的组件,apiserver.scheduler.controller manager.此外,master还依赖于ectd存储节点,最好ectd是有冗余能力的集群 ...

  7. Python装饰器笔记

    DRY(Don't Repeat Yourself)原则: 一般是指在写代码的时候尽量避免重复的实现.违反DRY原则导致的坏处很容易理解,例如维护困难,修改时一旦遗漏就会产生不易察觉的问题. 一.函数 ...

  8. Storm系列(七)架构分析之Scheduler-调度器[DefaultScheduler]

    Storm默认的任务调度器.实现如下: 1  (defn –prepare [this conf]) 2  (defn –schedule [this ^Topologies topologies ^ ...

  9. Storm系列(六)架构分析之Scheduler-调度器[EventScheduler]

    任务调度接口定义: 1  IScheduler{ 2      // conf为当前nimbus的stormp配置 3  void prepare(Map conf); // 初始化 4  // to ...

  10. Python 装饰器(笔记,非原创)

    定义:本质是函数,为其他函数添加附加功能原则:1.不能修改被装饰的函数的源代码         2.不能修改被装饰的函数的调用方式知识储备:       1.函数即“变量”       2.高阶函数  ...

随机推荐

  1. ubuntu配置docker全局系统代理

    (1)添加用户到docker用户组 sudo groupadd docker sudo gpasswd -a kang docker (注销系统当前用户,再次登录) #检查是否添加到组 cat /et ...

  2. pytorch自定义RNN结构(附代码)

    pytorch自定义LSTM结构(附代码) 有时我们可能会需要修改LSTM的结构,比如用分段线性函数替代非线性函数,这篇博客主要写如何用pytorch自定义一个LSTM结构,并在IMDB数据集上搭建了 ...

  3. NEO4J入门基础第二章

    1.简单导入CSV数据 Load CSV读取但不存入数据库: 查看前CSV文件行数 LOAD CSV FROM "file-url" AS line RETURN count(*) ...

  4. Python学习笔记(六)循环

    一.while循环 1.while在给定的判断条件为True时执行循环体,否则退出循环体 1 flag = True 2 while flag: 3 print('正确') 4 flag = Fals ...

  5. 常见的Native Crash类型,bug解决记录

    APP调用Native的jar包接口出现闪退,仅仅settings应用,其他应用调用该包接口正常使用. 猜测1. jar包为64为,settings程序为32位,版本兼容性问题.(经验证,原因确实如此 ...

  6. 【博客】如何在Github上创建博客

    [博客]如何在Github上创建博客 1. 安装nodejs windows安装npm教程--nodejs 2. 安装hexo npm install -g hexo-cli 3. 搭建博客 $ he ...

  7. python_test_0001_base_string_swap

    #!/usr/bin/python # -*- coding: UTF-8 -*- import time from lib_001_decorator_log_funcname import dec ...

  8. 【Java学习day04】Java文件的创建和Java代码的执行

    Java文件的创建和Java代码的执行 随便新建一个文件夹,存放代码 在新建的文件夹里新建一个java文件 新建一个文本文档 将新建的文本文档重命名为hello.java 注意了!后缀必须改为.jav ...

  9. 搭建ubuntu开发环境

    tar -xzvf  VMwareTools-10.0.6-3595377.tar.gz cd  vmware-tools-distrib 再执行:sudo ./vmware-install.pl  ...

  10. Go语言格式化金额为3个一组隔开

    最近在Go语言项目上面遇到了一个金额相关的问题,想更加规范的将金额用逗号隔开3个分为一组,这样显示更专业一点,经过一番努力,找到这个下面这个插件,经过测试发现比较好用,特此分享出来. 第一步先下载一个 ...