μC/OS-II与RT-Thread对比—任务调度
1. 任务控制块
(1)μC/OS-II
(2)RT-Thread
2. 任务调度模型
(1)μC/OS-II
(2)RT-Thread
就绪线程存在的情况下才有效。例如在 线程就绪优先级队列 图中,我们假设线程A和线程B一次最大允许运行的时间片分别是10个时钟节拍和7个时钟节拍。那么线程B将在线程A的时间片结束(10个时钟节拍)后才能运行,但如果中途线程A被挂起了,即线程A在运行的途中,因为试图去持有不可用的资源,而导致线程状态从就绪状态更改为阻塞状态,那么线程B会因为其优先级成为系统中就绪线程中最高的而马上运行。每个线程的时间片大小都可以在初始化或创建这个线程时指定。
3. 任务调度算法
(1)μC/OS-II
当OSRdyTbl[1]中的任何一位是1时,OSRdyGrp的第1位置1,
当OSRdyTbl[2]中的任何一位是1时,OSRdyGrp的第2位置1,
以些类推。。。。。
INT8U const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};//定位优先级所用
任务优先级的低三位用于确定任务在总就绪表OSRdyTbl[]中的所在位。接下去的[5:3]三位用于确定是在OSRdyTbl[] 数组的第几个元素。 OSMapTbl[]是在ROM中的(见文件OS_CORE.C)屏蔽字,用于限制OSRdyTbl[]数组的元素下标在0到7之间:
OSRdyGrp |= OSMapTbl[prio >> 3]; //先根据高3位[5:3]找到所在的组
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07]; //再由低3位把该组的具体某一位置1
if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
OSRdyGrp &= ~OSMapTbl[prio >> 3];
以上代码将就绪任务表数组OSRdyTbl[]中相应元素的相应位清零,而对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时,才将相应位清零。也就是说OSRdyTbl[prio>>3]所有的位都是零时,OSRdyGrp的相应位才清零。为了找到那个进入就绪态的优先级最高的任务,并不需要从OSRdyTbl[0]开始扫描整个就绪任务表,只需要查另外一张表,即优先级判定表 OSUnMapTbl ([256])(见文件OS_CORE.C)。OSRdyTbl[]中每个字节的8位代表这一组的8个任务哪些进入就绪态了,低位的优先级高于高位。利用这个字节为下标来查OSUnMapTbl这张表,返回的字节就是该组任务中就绪态任务中优先级最高的那个任务所在的位置(即该字节的中最低位1的所在位)。这个返回值在0到7之间。确定进入就绪态的优先级最高的任务是用以下代码完成的。
找出进入就绪态的优先级最高的任务
y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
prio = (y << 3) + x;
INT8U const OSUnMapTbl[] = {
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};//定位最高优先级用(即查找一个字节的最低位1所在的位置)
例如,如果OSRdyGrp的值为二进制01101000,查OSUnMapTbl[OSRdyGrp]得到的值是3,它相应于OSRdyGrp中的第3 位bit3,这里假设最右边的一位是第0位bit0。类似地,如果OSRdyTbl[3]的值是二进制11100100,则OSUnMapTbl [OSRdyTbc[3]]的值是2,即第2位。于是任务的优先级Prio就等于26(3*8+2)。利用这个优先级的值。查任务控制块优先级表 OSTCBPrioTbl[],得到指向相应任务的任务控制块OS_TCB的工作就完成了。
(2)RT-Thread
优先级125 对应那个字节的哪个bit呢?
这里有个换算关系。其计算公式 :
(优先级别 / 8 )商取整数即对应位图中的字节 (优先级别 % 8 )就是对应位图字节中的bit位,即优先级125, 125 / 8 = 15 , 125 %8 = 5. 位图的BIT125就是 rt_thread_ready_table[15]的BIT5
rtt中对应的数组为rt_uint8_t rt_thread_ready_table[32]
所谓二级位图,即我们先确定32个字节中最低的非0的字节。为了实现这个效果,我们需要对这32个字节引入一个32个bit的位图变量,每一个bit位表示对应的字节是否为0。例如,这个32bit的位图变量的BIT5为0,表示系统线程优先级256bit所分成的32个字节中的 字节5 非0。 为了区分,称这个32个bit的位图变量 字节位图变量 ,rt-thread中使用的是rt_thread_ready_priority_group. 显然我们查找系统系统最高优先级时,先确定非0的最低字节,这实际上依然是算法3,然后再对该字节进行查表,即得到该字节内最低为1的bit位,然后两者叠加(注意不是简单的加)即可。
根据上面的分析,要想使用这个二级位图算法,rtt在跟踪线程的状态转换时,不仅需要维护256bit的位图变量数组rt_thread_ready_table[thread->number] |= thread->high_mask,还需要维护32bit的 字节位图变量 rt_thread_ready_priority_group。参看如下代码。
语句(1)thread->current_priority >> 3,这里的>>3就是除以8,因为一个字节表示8个优先级。这样就可以得到当前这个优先级对应的位图32个字节中的第几个字节,这里用thread->number表示,显然,number范围是0到31。这里为了提高效率,采用移位完成除法。
上面除法的余数,就表示这个优先级在上面字节中的第几个bit。这个余数可以使用 (thread->current_priority & 0x07)来表示。
语句(3)是得到该bit对应的权值。例如一个字节的bit7对应的权值即 (1<<7),这样做是为了使用“位与,或,非”等位运算,可以提高运行速度,即语句(4)。
语句(4)清楚表示了这几个变量作用。可见,根据某个表示优先级的数字向位图中相应的bit位写入了1。
那么语句(2)和(5)是做什么用的呢? 这个number_mask实际上是为了加快查找位图的速度而创建的。它将在rt_schedule函数中发挥作用。
上文已说明,thread->number就表示当前线程优先级在32个字节的位图数组中的字节位置。为了提高效率,rt-thread另外使用了一个u32类型的变量rt_thread_ready_priority_group 来加快速度。如果这32个bit中某一个bit为1,就表示对应的某个字节非0(想想看,这意味着该字节所表示的8个优先级中存在就绪线程)。
rt_thread_ready_priority_group变量为32位宽度,长度上等于4个字节,因此可以对每一个字节查表(上面生成的表格)就可以得到为1的最低的bit位置。
概括起来就是,rtt首先确定32个字节的位图中,非0的最低的那个字节,然后再查表得到这个字节非0的最低那个bit。这两步骤正好可以利用两次上面的表格rt_lowest_bitmap。
下面附上rt_schedule的代码。非必要的代码被我隐去。读者可以对比下面的代码理解上面的思路。
4. 总结
μC/OS-II与RT-Thread对比—任务调度的更多相关文章
- uC/OS II原理分析及源码阅读(一)
uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的.可裁减的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和 ...
- 【原创】uC/OS II 任务切换原理
今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS.IP寄存器没有出栈和入栈指令,所以只能引 ...
- 【小梅哥SOPC学习笔记】NIOS II处理器运行UC/OS II
SOPC开发流程之NIOS II 处理器运行 UC/OS II 这里以在芯航线FPGA学习套件的核心板上搭建 NIOS II 软核并运行 UCOS II操作系统为例介绍SOPC的开发流程. 第一步:建 ...
- RT Thread 通过ENV来配置SFUD,操作SPI Flash
本实验基于正点原子stm32f4探索者板子 请移步我的RT Thread论坛帖子. https://www.rt-thread.org/qa/forum.php?mod=viewthread& ...
- STM32 + RT Thread OS 学习笔记[二]
串口通讯例程 通过上面的练习,对STM32项目开发有了一个直观印象,接下来尝试对串口RS232进行操作. 1. 目标需求: 开机打开串口1,侦听上位机(使用电脑串口测试软件)发送的信息,然后原样输 ...
- STM32 + RT Thread OS 串口通讯
1. 创建项目 a) 禁用Finsh和console b) 默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1.因 ...
- STM32 + RT Thread OS 学习笔记[三]
RTGUI 据说RTGUI是多线程的,因此与RT-Thread OS的耦合度较高,有可能要访问RT-Thread的线程控制块.如果要移植到其它OS,估计难度较大.目前还处于Alpha状态,最终将会包含 ...
- STM32 + RT Thread OS 学习笔记[四]
1. 补注 a) 硬件,打通通讯通道 若学习者购买了学习板,通常可以在学习板提供的示例代码中找到LCD的相关驱动代码,基本上,这里的驱动的所有代码都可以从里面找到. 从上面的示意图可见,M ...
- μC/OS-II与RT-Thread对比——任务调度
在任务调度器的实现上,μC/OS-II和RT-Thread都采用了位图调度(bitmap scheduling),任务优先级的值越小则代表具有越高的优先级,主要区别在于实现形式,是采用多 ...
随机推荐
- 有一个投篮游戏。球场有p个篮筐,编号为0,1...,p-1。每个篮筐下有个袋子,每个袋子最多装一个篮球。有n个篮球,每个球编号xi 。规则是将数字为xi 的篮球投到xi 除p的余数为编号的袋里。若袋里已有篮球则球弹出游戏结束输出i,否则重复至所有球都投完。输出-1。问游戏最终的输出是什么?
// ConsoleApplication5.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<vector> ...
- API -- 图书
豆瓣IAPI:https://developers.douban.com/wiki/?title=book_v2#get_isbn_book 其他:http://www.cnblogs.com/sop ...
- 嵌入式开发之davinci--- 8148/8168/8127 中的xdc 简介
XDC是TI公司为嵌入式实时系统可重用软件组件(在XDC里被成为packages,以下成为包)制定的一套标准.它包括一些有用的工具,标准的API函数,静态配置文件和打包(packaging)操作.XD ...
- SERVICE_STATUS结构各成员解析
在编写Windows服务的时候,需要调用API函数::SetServiceStatus()向服务控制管理器(SCM)提交更新当前服务的状态信息,其第2个参数为指向SERVICE_STATUS结构的指针 ...
- python 基础 1.5 python 数据类型(一)--整型 浮点型 布尔型及字符串和常用方法
一.python 数据类型:数值,字符串,列表,元组,字典.以下操作是在linux 下 ipython中进行 1.数值 1>123 与 “123”的区别 答:123为数值,“123”在pyt ...
- 【BZOJ4197】[Noi2015]寿司晚宴 状压DP+分解质因数
[BZOJ4197][Noi2015]寿司晚宴 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴 ...
- 借助nodejs解析加密字符串 node安装库较python方便
const node_modules_path = '../node_modules/' // crypto-js - npm https://www.npmjs.com/package/crypto ...
- django 设置静态文件,static 链接
这篇文章讲的django 静态static 文件设置,还可以,供参考 http://blog.csdn.net/sinat_21302587/article/details/74059078
- Cordova插件相关常用命令
一,插件相关常用命令 1,查看所有已经安装的插件 1 cordova plugin ls 2,安装插件(以camera插件为例) 1 cordova plugin add cordova-plug ...
- gradle 跳过junitTest的方法
Web项目中不长会写JunitTest,但也会写.gradle build的时候回执行test 这项task.如果想跳过,通常有几种方法: 1.在build.gradle 文件中禁用task test ...