μcOS-II多任务实验报告(RMS、EDF调度)

一、实验概述

  • 实验目的:在ucOS-II上多任务实验,要求考虑到任务间存在共享资源的情况。
  • 本次实验使用到的调度策略为RMS和EDF。
  • 其中RMS为固定优先级的调度,其实就是从就绪态中找到优先级最大的,就是周期最小的让它进入运行态。
  • 而EDF调度起源于EDD算法,EDD算法要求最小化最大延迟,只要将ddl近的设为高优先级就行了,而EDF要求进一步支持任务在任意时间到达,即EDF需要动态的维持任务的优先级。
  • 共享资源利用信号量OSSemCreate(1)实现
  • 备注:在提交的作业中,我把Sched_EDF()注释掉了,默认输出结果是RMS调度(有共享资源)。想看EDF的结果就到oscore.c中,找到OS_SchedNew(),把RMS调度注释掉,清除EDF的注释。想看无共享资源就到main.c,找到对任务resource初始化的代码,注释掉即可。

二、环境搭建

本实验使用的μcOS-II系统,是移植到VS2017上的。在打开解决方案OS2.sln后,发现其使用的Windows SDK版本较旧,因此需要在项目属性中重新指定SDK版本。重新配置后,项目能够正常编译运行。

三、代码分析

在借助资料,研读代码执行流程后,我认识到:

  • 任务在main.c中创建,新建任务后会生成对应的TCB程序控制块(定义在ucos-ii.h中的OS_TCB),并链接到TCB链表中头,链表尾是程序创建的空闲任务。
  • 任务在while中无限循环,cpu利用TimeTick(在os_cpu_c.c中)在这些任务中切换。每隔一段时间中断,中断调用函数OSTickW32,顺序执行OSIntEnter()、OSTimeTick()、OSIntExit()、OSIntCurTaskResume()。
  • 中断主要使用的函数OSTimeTick()在os_core.c中,它会遍历OSTCBList,将所有TCB的等待时间(ptcb->OSTCBDly)减一,如果那个TCB的等待时间变成0了,就把它的优先级添加到任务就绪表。
  • 再看OSIntExit(),也在os_core.c中,通过OSPrioHighRdy,然后去OSTCBPrioTbl数组找到了对应的TCB,赋值给OSTCBHighRdy指针。然后调用了上下文切换函数OSIntCtxSw()函数(用来切换线程,修改了OSTCBCur,OSPrioCur)。
  • 值得注意的是,在OSIntExit()中程序是通过OS_SchedNew()来取得当前就绪态中优先级最高的TCB块的,用OSPrioHighRdy表示。
  • 而OS_SchedNew()(同在os_core.c中),仅仅通过三行关键代码(就在<=63的那个if里)就完成了对RMS的支持。如果想修改调度算法,应该就是改这里了。

四、实验步骤

1 给TCB块添加扩展

如下图所示,定义在ucos_ii.h中的OS_TCB下面,在创建任务时作为TCB扩展传入。OS_TCB的OSTCBExtPtr指针指向的就是这个tcb_ext_info。目的是为执行任务时提供必要的信息

2 创建并执行任务

  • 如下图所示,进行了任务创建(createTasks)与任务执行(startTasks)。都在main.c中。

  • 任务创建要初始化resource,即信号量的事件控制块指针,然后使用OSTaskCreateExt()方法创建任务。其中任务的id号=任务的优先值=任务的周期数。因为任务的优先级和任务的优先值成反比。其中对于RMS调度,任务的优先级与任务的周期成反比,也就是说任务优先值是可以直接用周期表示的。其中对于EDF调度,这个动态优先级调度,也省得我重新为三个任务指定初始优先值,对于这个用例我就默认任务初始优先值等于周期长度。

  • 任务执行先使用while循环来做一个周期的任务,利用时钟中断来切换任务。所以这个周期可能会顺利执行完,也有可能被抢占,执行可能会请求信号量。一个周期做完了,要重置rest_c并记得归还信号量。







3 添加时钟中断对剩余执行时间和剩余周期的操作

在os_core.c中每次timetick,把执行任务的rest_c减去1,并遍历TCB,把所有任务的rest_p减去1,并看哪个任务已经OSTCBDly已经为0,即进入就绪态时再重置任务的rest_p。

4 实现调度

注释掉OS_SchedNew()中的函数,在结尾插入我的新函数Sched_RMS和Sched_EDF()。

4.1 RMS调度

考虑到要实现共享资源,这三行代码还不太利于我操作,尤其是目前我对代码了解还不深的情况下。考虑到RMS较为简单,我就用自己添加的数据结构重新写了RMS调度。重新写好处是,一来EDF完全可以复用它,只要把就绪态中周期最小的改为就绪态中剩余周期最小的就行了;二来,这样方便我过滤掉就绪态中资源被别的任务占用的任务。

主要思路是初始优先级选63,遍历TCB链表(不包括61,62),找到就绪态中可请求资源或无需资源的任务中优先级最高(周期最短)的任务,如果需要请求资源,就给它资源。



4.2 EDF调度

EDF复用RMS的代码,只要把就绪态中周期最小的改为就绪态中剩余周期最小的就行了。



5 输出

两种输出,任务完成与任务抢占

  • 任务完成会调用OSTimeDly(),完成的printf写在该函数里
  • 任务抢占会走OSIntExit(),在该函数里判断一下是不是抢占,如果是就printf抢占的内容。

6 结果展示

6.1 RMS 无共享资源

6.2 EDF 无共享资源

6.3 RMS 有共享资源(最高优先级和最低优先级共享)

6.4 EDF有共享资源(最高优先级和最低优先级共享)

五 值得注意的部分

  • 遍历的时候要注意不单单有优先级为63的空闲任务,我还发现了有优先级为62、61的任务,为了方便输出的观察,我是直接将其过滤掉,不让其影响我的输出。
  • 注意可能存在这种情况,在B任务执行结束时,即rest_c=0时,如果A任务优先级高于B,会发生A先抢占B,然后A执行完之后……然后B任务才能complete。这点给我造成了很大的两点麻烦。
    • 一个是我不希望造成A抢占B,然后某任务再还给B的这种输出,而是应该让B直接完成,然后再让A做其他操作。这个我是通过给任务抢占的判断添加限制条件(在任务抢占输出那一部分),让B能跳过被抢占,直接完成,完成后再转给A。
    • 另一个是我不希望由于A抢占B,B不能立即complete造成资源还在B手里,不能归还,影响其它任务的执行。这点我通过在调度函数最后请求资源时做条件判断,避免了这种情况。
  • 给代码加入信号量部分后,发现代码运行出问题了,导致进入临界区函数OS_ENTER_CRITICAL()没法使用了,导致下面代码运行不了。在找到该函数源码后,依据网上给的思路,我试着换到另一个if判断,并注释掉了一部分代码后,能够正常运行。
  • 还有一个问题是,时钟频率太快导致代码来不及运行,这个我一开始不知道,毫无办法,后来把os_cfg.h文件中#define OS_TICKS_PER_SEC 从100改成10,这样运行就没问题了。

六 源码

github源码

基于μcOS-II实时操作系统源码实现RMS和EDF调度(共享资源)的更多相关文章

  1. 适合新手:从零开发一个IM服务端(基于Netty,有完整源码)

    本文由“yuanrw”分享,博客:juejin.im/user/5cefab8451882510eb758606,收录时内容有改动和修订. 0.引言 站长提示:本文适合IM新手阅读,但最好有一定的网络 ...

  2. 基于vitamio的网络电视直播源码

    这个项目是基于vitamio的网络电视直播源码,也是一个使用了vitamio的基于安卓的网络直播项目源码,可能现在网上已经有很多类似这样的视频播放应用了,不过这个还是相对来说比较完整的,希望这个案例能 ...

  3. 第6章 RTX 操作系统源码方式移植

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章教程为大家将介绍 RTX 操作系统源码方式移植,移植工作比较简单,只需要用户添加需要的源码文件即可, ...

  4. 基于jQuery经典扫雷游戏源码

    分享一款基于jQuery经典扫雷游戏源码.这是一款网页版扫雷小游戏特效代码下载.效果图如下: 在线预览   源码下载 实现的代码. html代码: <center> <h1>j ...

  5. Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析

    Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析 本文简要介绍了基于 Spring 的 web project 的启动流程,详细分析了 Spring 框架将开发人员基于 XML ...

  6. Spark源码分析之六:Task调度(二)

    话说在<Spark源码分析之五:Task调度(一)>一文中,我们对Task调度分析到了DriverEndpoint的makeOffers()方法.这个方法针对接收到的ReviveOffer ...

  7. 基于Linux平台的libpcap源码分析和优化

    目录 1..... libpcap简介... 1 2..... libpcap捕包过程... 2 2.1        数据包基本捕包流程... 2 2.2        libpcap捕包过程... ...

  8. 基于ReentrantLock的AQS的源码分析(独占、非中断、不超时部分)

    刚刚看完了并发实践这本书,算是理论具备了,看到了AQS的介绍,再看看源码,发现要想把并发理解透还是很难得,花了几个小时细分析了一下把可能出现的场景尽可能的往代码中去套,还是有些收获,但是真的很费脑,还 ...

  9. Android版数据结构与算法(二):基于数组的实现ArrayList源码彻底分析

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 本片我们分析基础数组的实现--ArrayList,不会分析整个集合的继承体系,这不是本系列文章重点. 源码分析都是基于"安卓版" ...

随机推荐

  1. [POJ1985] Cow Marathon 「树的直径」

    >传送门< 题意:求树的直径 思路:就是道模板题,两遍dfs就求出来了 Code #include <cstdio> #include <iostream> #in ...

  2. Codeforces Round #690 (Div. 3)

    第一次 ak cf 的正式比赛,不正式的是寒假里 div4 的 Testing Round,好啦好啦不要问我为什么没有 ak div4 了,差一题差一题 =.= 不知不觉已经咕了一个月了2333. 比 ...

  3. AtCoder Beginner Contest 188 E - Peddler (树)

    题意:有\(n\)个点,\(m\)条单向边,保证每条边的起点小于终点,每个点都有权值,找到联通的点的两个点的最大差值. 题解:因为题目说了起点小于终点,所以我们可以反向存边,然后维护连通边的前缀最小值 ...

  4. zoj3623 Battle Ships

    Battle Ships is a new game which is similar to Star Craft. In this game, the enemy builds a defense ...

  5. Educational Codeforces Round 94 (Rated for Div. 2) A. String Similarity (构造水题)

    题意:给你一个长度为\(2*n-1\)的字符串\(s\),让你构造一个长度为\(n\)的字符串,使得构造的字符串中有相同位置的字符等于\(s[1..n],s[2..n+1],...,s[n,2n-1] ...

  6. 2017, X Samara Regional Intercollegiate Programming Contest E. Bonuses and Teleports (思维,模拟)

    题意:在\(x\)轴上有很多传送点和钻石,当位于传送点上时,可以传送到其他任意传送点(不记操作数),位于钻石上时可以吃掉它,每次可以移动一个单位,问最少多少次可以吃掉所有的钻石. 题解:对于某个位置上 ...

  7. C# 程序运行时间计算

    https://www.cnblogs.com/dearzhoubi/p/9842452.html

  8. 继承自List<T>的类通过NewtonJson的序列化问题

    什么问题? NewtonSoft.Json是我们最常用的Json组件库之一了.这里来讨论下使用NewtonSoft.Json序列化List<T>子类的情景.序列化使用了类JsonSeria ...

  9. 手把手教你通过SQL注入盗取数据库信息

    目录 数据库结构 注入示例 判断共有多少字段 判断字段显示位置 显示出登录用户和数据库名 查看所有数据库 获取对应数据库的表 获取对应表的字段名称 获取用户密码 SQL注入(SQL Injection ...

  10. 弹性伸缩 AS(Auto Scaling)

    根据业务需求和策略设置伸缩规则,在业务需求增长时自动为您增加 ECS 实例以保证计算能力,在业务需求下降时自动减少 ECS 实例以节约成本,弹性伸缩不仅适合业务量不断波动的应用程序,同时也适合业务量稳 ...