就绪表作用

操作系统内核会将就绪的任务存放在就绪表,内核总是从就绪表中找出最高优先级任务,并执行该任务。
内核调度任务时只用关注就绪表,从就绪表中最高优先级项中选择任务并执行。

就绪表是存放就绪任务的列表,就绪表通常有两个项目:优先级,任务成员。同一个优先级的任务放在就绪表中的同一个优先级列表项中,就绪表框架如下:

构建就绪表
使用静态数组的方式可以构建一个就绪表,代码实现如下:

其中tcb_item_t为 TCB项 ,list_item_t列表项,ready_list为就绪表。
就绪表中包含了10个列表,每个列表对应一个优先级,ready_list[0]表示优先级0的任务列表,ready_list[9]表示优先级9的任务列表。
ready_list中的每个列表包含10个TCB项,itme[0]表示该优先级下的任务0,itme[9]表示该优先级下的任务9。
每个TCB项中包含一个标志位和TCB指针,TCB指针指向任务的TCB数据结构。数据结构图如下:

使用静态数组方式的优点是:结构简单,使用方便。但是使用静态数组的缺点非常明显:
1、每个一优先级容纳的任务数量是固定的,一旦需要增加某个优先级任务数量,整个列表大小将增加。
2、在同一个优先级任务中间插入一个任务,需要移动多个TCB项。
3、存在多个优先级未用的情况,导致内存浪费严重。
综合上述问题,因此使用静态数组的方式是不明智的选择。
但是这种数据结构能让我们认清就就绪表的本质:就绪表分为多个优先级,就绪表的每个优先级可以容纳多个任务。

构建就绪表可以使用双向链表的方式,代码实现如下:

list_item_t列表项,ready_list为就绪表。
就绪表中包含了10个列表,每个列表对应一个优先级,ready_list[0]表示优先级0的任务列表,ready_list[9]表示优先级9的任务列表。
每个list_item_t列表中包含一个TCB指针,下一个列表项指针和上一个列表项指针。数据结构图如下:

使用双向链表的方式有以下优点:
1、每一个链表可以连接任意数量的链表项,长度不受限制。
2、链表的每一项,都是有用项,不存在内存浪费
3、在链表中间插入一项,操作效率较高。
使用双向链表构建就绪表是很好的选择

就绪表源码分析
接下来我们一起来分析FreeRTOS就绪表的源码,源码如下:

根据源码可知:FreeRTOS就绪表由链表组成
pxReadyTasksLists为就绪表,就绪表中包含10个列表,pxReadyTasksLists[0]表示优先级0的任务列表,pxReadyTasksListst[9]表示优先级9的任务列表。
每个列表包含一个xListEnd项,xListEnd中包含下一个列表项指针和上一个列表项指针。

FreeRTOS中的TCB结构,根据源码可知TCB内部有名为xStateListItem的列表项(ListItem_t),就绪表中的列表项xListEnd指针指向TCB结构中的列表项。

FreeRTOS的就绪表和任务TCB关系框图如下:

就绪表操作
操作系统内核总是选择最高优先级的任务运行,相同优先级的任务轮流运行。
针对这种调度原则,内核只需要从就绪表中找出最高优先级任务列表pxReadyTasksLists[n],运行该列表中第一个列表项指向的任务,任务运行完毕后内核将任务插入列表的尾部,然后内核再运行该任务列表中第一个列表项指向的任务,从而实现轮流运行。新任务加入就绪表时,总是插入到对应优先级列表的尾部。
根据应用要求,内核还可以移除列表中任意位置的列表项。

内核操作就绪表有三个基本操作:
1、头部取出,内核总是从最高优先级列表中取出第一个列表项任务运行。
2、尾部插入,任务运行完毕或者新任务加入就绪表时,总是插入到对应优先级列表的尾部。
3、任意位置移除,内核可以移除列表中任意位置的列表项。

FreeRTOS的就绪表操作源码:

prvAddTaskToReadyList 的功能是将任务加入就绪表, vListInsertEnd 的功能是将任务插入列表尾部。

taskSELECT_HIGHEST_PRIORITY_TASK的功能是选择最高优先级任务,listGET_OWNER_OF_NEXT_ENTRY 的功能是从该优先级列表中取出第一个列表项。

uxListRemove的功能是在列表中移除指定的一个列表项。

就绪表更新
上一节描述了内核操作就绪表的三个基本操作:头部取出,尾部插入,任意位置移除。那么哪些位置会对就绪表进行操作?操作系统会在如下位置更新就绪表(参考FreeRTOS):

xTaskCreate
xTaskCreate的作用是创建一个任务,该系统函数的调用流程如下:
xTaskCreate -> prvAddNewTaskToReadyList -> prvAddTaskToReadyList -> vListInsertEnd
就绪表变化:任务插入到就绪表对应优先级列表的尾部。

vTaskDelete
vTaskDelete的作用是删除一个任务,该系统函数的调用流程如下:
vTaskDelete -> uxListRemove
就绪表变化:任务从就绪表对应优先级列表中移除

vTaskSuspend
vTaskSuspend的作用是暂停一个任务,该系统函数的调用流程如下:
vTaskSuspend -> uxListRemove
就绪表变化:任务从对应优先级列表中移除

vTaskResume
vTaskResume的作用是恢复一个任务,该系统函数的调用流程如下:
vTaskResume -> prvAddTaskToReadyList -> vListInsertEnd
就绪表变化:任务插入到就绪表中对应优先级列表的尾部。

vTaskPrioritySet
vTaskPrioritySet的作用是改变一个任务优先级,该系统函数的调用流程如下:
vTaskPrioritySet ->uxListRemove -> prvAddTaskToReadyList -> vListInsertEnd
就绪表变化:任务从就绪表中的当前优先级列表中移除,并将任务插入到设定的优先级列表的尾部。

vTaskDelay
vTaskDelay的作用是将当前任务从就绪表中移动到等待表中,该系统函数的调用流程如下:
vTaskDelay -> uxListRemove -> vListInsert
就绪表变化:任务从就绪表中移除,并将任务插入到等待表中。

xQueueSemaphoreTake
xQueueSemaphoreTake的作用是当前任务等待一个信号,该系统函数的调用流程如下:
xQueueSemaphoreTake -> vListInsert -> prvAddCurrentTaskToDelayedList -> uxListRemove -> vListInsert
就绪表变化:将当前任务插入到挂起中,并当前任务从就绪表中移除,最后将当前任务插入等待表中。

xQueueGenericSend
xQueueSemaphoreTake的作用是发生一个信号,该系统函数的调用流程如下:
xQueueGenericSend -> xTaskRemoveFromEventList-> uxListRemove -> prvAddTaskToReadyList -> vListInsertEnd
就绪表变化:将移除挂起表中的第一个任务,并该任务插入到就绪表中中对应优先级列表的尾部。

就绪表框图

TCB设计

增加任务的TCB结构:

TCB中包含了:
1、栈指针。
2、任务状态列表。
3、任务事件列表。
4、优先级。
5、栈起始地址
6、任务名

TCB结构,寄存器堆和任务栈的关系图如下:

静态区定义的任务TCB对象中的栈指针指向任务栈区的栈顶,任务栈区保存着寄存器堆的数据,寄存器堆中的PC值指向任务的代码区,任务状态列表和任务事件列表与就绪表,等待表和挂起表关联。

未完待续…
实时操作系统系列将持续更新
创作不易希望朋友们点赞,转发,评论,关注。
您的点赞,转发,评论,关注将是我持续更新的动力
作者:李巍
Github:liyinuoman2017

嵌入式实时操作系统5——就绪表相关推荐

  1. 嵌入式实时操作系统11——操作系统内核运行原理

    先展示一个操作系统运行动态图 1.操作系统内核关键知识点 本文将用一个实际的工程例子来剖析操作系统内核运行原理.在此之前我们先回顾一下之前文章讲述的重点知识点. <嵌入式实时操作系统3--任务切 ...

  2. 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十六章 UCOSII 实验 1任务调度...

    1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十六章 ...

  3. 嵌入式实时操作系统1——初识嵌入式实时操作系统

    嵌入式实时操作系统是什么 嵌入式实时操作系统是一个特殊的程序,是一个支持多任务的运行环境.嵌入式实时操作系统最大的特点就是"实时性",如果有一个任务需要执行,实时操作系统会立即执行 ...

  4. 嵌入式实时操作系统μC/OS II(一)

    嵌入式实时操作系统μC/OS II 为什么要学习μC/OS-II ㈠.凡从事嵌入式系统开发工作的人,必须对嵌入式操作系统有足够的了解. ㈡.对于初学者,从μC/OS-II开始是个明智的选择. 1.μC ...

  5. 嵌入式实时操作系统-VxWorks(基础)

    1.实时系统定义:是指那些产生系统输出的时间对于系统是至关重要的系统. 实时系统可根据时限对其性能(或效益)影响程度的不同,分为软实时系统SRT和硬实时系统HRT. 软时限是指时限的错过不会损害系统的 ...

  6. 《嵌入式实时操作系统uC/OS-II》学习摘要

    二. 实时系统概念 1.实时系统的特点 如果逻辑和时序出现了偏差,将会引起严重后果.有两种类型的实时系统:软实时系统和硬实时系统. 在软实时系统系统中,系统的宗旨是指各个任务尽快地运行,而不要求限定某 ...

  7. 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十八章 UCOSII 实验 3...

    1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十八章 ...

  8. 从零开始构建嵌入式实时操作系统2——重构

    1.前言 本人是一个普通的中年程序员,并不是圈内的大牛,写嵌入式操作系统这一系列的文章并不是要显示自己的技术,而是出于对嵌入式的热爱.非常幸运,本人毕业后的十几年一直从事嵌入式行业,遇到过各种坑,也收 ...

  9. 嵌入式实时操作系统μC/OS-Ⅱ 在DSP芯片上的移植与测试

    [摘要]为了降低DSP 系统软件的开发难度,保证系统的实时性,缩短开发周期,将嵌入式实时操作系统μC/OS-Ⅱ移植到DSP 芯片中是目前比较常用的一种方法.本文介绍了嵌入式实时操作系统μC/OS-Ⅱ的 ...

最新文章

  1. python符号求导
  2. 理解事件捕获。在限制范围内拖拽div+吸附+事件捕获
  3. 揭开Socket编程的面纱
  4. hdu 3172(并查集+hash)
  5. SAP CRM WebClient UI交互式报表的Gross Value工作原理
  6. uClinux下移植Ne2000兼容的网卡驱动程序(转)
  7. 使用可自定义的定期计划自动执行数据库备份
  8. SVN工作笔记004---svn查看log提示_offline
  9. 创建目录 java_java创建文件和目录
  10. 算术编码python实现_算术编码(Arithmetic coding)的实现
  11. 01-jbpm工作流实现
  12. 强网杯2021CTF 强网先锋shellcode侧信道攻击复现
  13. WIFI密码破解笔记
  14. lintcode 输出赛程表
  15. 准备半年,面试2个月,上岸快手拿个35K应该不算高吧?
  16. c语言 谭浩强第五版第五章习题第17题 乒乓球比赛
  17. Towards Better Understanding of Self-Supervised Representations / Q-Score
  18. Hive2.1函数列表
  19. 【PSO】量子粒子群算法(QPSO)
  20. 服务器omv系统,在Debian上安装OpenMediaVault开源NAS系统

热门文章

  1. 交换机配置VLANIF
  2. 如何做小红书封面?笔记要爆封面设置少不了
  3. 浅谈JavaScript中的Number类型
  4. 基于FPGA 的图像缩放算法设计
  5. ESP8266的低功耗方案-睡眠模式
  6. 在H5页面中禁止微信分享转发按钮-mugeda
  7. html + css 实现一个炫酷的照片墙
  8. 刘强东年底每天要开一千家店;联通将关2G;王兴否认摩拜裁员丨价值早报
  9. figma设计用户头像效果
  10. 第八课:条件判断语句