当前位置: 首页> 健康> 美食 > 任务状态与调度

任务状态与调度

时间:2025/7/10 3:20:04来源:https://blog.csdn.net/m0_47239466/article/details/140643452 浏览次数:0次
  • 任务状态:在任务创建和删除的基础上添加了任务的暂停和恢复
  • 调度

目录

一、任务状态(Freertos)

1、任务的状态(Freertos)

2、借助音乐播放器程序剖析状态

在创建任务函数中:

新创建的3个任务属于ready状态​编辑

音乐播放任务的创建和删除在默认任务里,其状态剖析如下:

3、添加音乐暂停和恢复功能

在函数中传入句柄就实现任务状态的暂停与恢复

二、任务管理

1、调度:

结论:

2、任务优先级管理举例

(1)任务组成的链表放在数组中

(2) 启动内核时在任务调度器中会创建优先级为0的空闲任务

(3)链表中的指针pxCurrent

(4)任务调用

1/第一次调度:

2/第二个时钟周期

*在默认任务中创建了优先级更高的任务

按下暂停键:把任务放入suspended链表

按下播放键:把任务从suspended链表放回ready链表 

系统时钟Tick中断:

Q:各个任务切换任务状态保存在TCB结构体?

Q:任务和线程的关系

一、任务状态(Freertos)

1、任务的状态(Freertos)

  1. 就绪状态(ready):可以随时执行(只要有机会切换,就可以变为running状态)
  2. 执行状态(running):正在执行(被调度出去后变为ready状态)(调用到阻塞函数会切换到阻塞状态)
  3. 阻塞状态(Blocked):等待某些事件
  4.  暂停状态(Suspended):暂停当前工作。(自己running时,调用函数;别人runnning,自己ready或block时,别人调用函数

2、借助音乐播放器程序剖析状态

main.c

初始化内核

创建任务

启动调度器

在创建任务函数中:

新创建的3个任务属于ready状态
音乐播放任务的创建和删除在默认任务里,其状态剖析如下:
  • 音乐播放的优先级高,所以先执行,处于running状态;
  • 音乐播放函数中的延迟函数为阻塞函数,处于Blocked状态(等待其他任务执行);
  • 当时间到之后,就会被唤醒,进入ready就绪状态,在能运行的时候变为running状态

PS:声音播放函数 中的阻塞函数

PS:阻塞函数:等待某些时间或等待某些数据————同步与互斥

3、添加音乐暂停和恢复功能

在函数中传入句柄就实现任务状态的暂停与恢复

resume后的运行和running不是一回事?

答:继续执行任务(该任务可能在阻塞态可能在运行态)

PS:暂停的时候要停止蜂鸣器,否则蜂鸣器保持一个音调

二、任务管理

1、调度:

  • 相同优先级 的任务轮流运行
  • 最高优先级 的任务先运行

结论:

  1. 只要有高优先级的未执行完,低优先级的无法运行
  2. 一旦高优先级任务就绪,马上运行高优先级
  3. 若最高优先级的任务有多个,他们轮流运行

在代码中通过链表进行任务的管理

2、任务优先级管理举例

(1)任务组成的链表放在数组中

最高优先级 的个数

数组中 的56项目,每一项都是一个链表 

第n项放的是: 优先级为n的处于ready状态的任务

(2) 启动内核时在任务调度器中会创建优先级为0的空闲任务

启动内核

任务调度器

创建空闲任务

(3)链表中的指针pxCurrent

创建任务函数中把任务加入就绪链表

 在就绪链表函数中有优先级判断

一开始没有其他任务。所以指向第一个任务;

当创建同级任务时,pxCurrent指向同级的新任务;

当执行内核启动函数时,因空闲任务的优先级较低,故pxCurrent不变

当启动调度器时,从pxCurrent开始,先运行最后创建的任务

(4)任务调用

执行完任务3重新发起调度

1/第一次调度:

每1ms产生一次时钟中断 

调度(遍历ReadyList),找到第一个非空的链表

 

2/第二个时钟周期

TICK中断:运行1ms后会再次触发Tick中断,计数值累加,再次发起调度

调度机制:再次从上到下遍历链表,找出非空的链表中下一个要执行的任务

*在默认任务中创建了优先级更高的任务

  1. 任务在创建后为就绪状态,因优先级最高,所以打断本时钟周期内的其他任务,优先执行该任务;
  2. 当执行到延时函数(延时2s)时,为就绪状态,会被从Ready列表中删除,移到某一个DelayTaskList;
  3. 当执行到延时函数时会触发调度,依据记录index取出下一个任务来运行
  4. 在两次时钟中断后,会发起一个调度,在去遍历就绪链表前,先到Delay链表,判断Delay链表中的任务是否可恢复,到时间的话就把这个任务放入就绪链表

 

按下暂停键:把任务放入suspended链表

按下播放键:把任务从suspended链表放回ready链表 

系统时钟Tick中断:

  1. 累加计数cnt++
  2. DelayedTaskList中处于阻塞态的任务是否可以恢复(是否到时)为就绪态
  3. 遍历就绪链表

三、空闲任务

作用:

释放被删除的任务的内存

避免调度时其他任务阻塞的情况

1、任务的函数不是死循环,所有任务都无法再次执行,(将会返回错误函数)

1、在错误函数中会关闭Tick中断,导致任务无法切换,之后陷入错误函数的死循环

2、如果任务 不是死循环会退出的代码

任务创建函数调用初始化栈

 {

在初始化栈时伪造好LR寄存器的值(错误函数)(在函数执行完要返回到LR寄存器所指示的位置)

{ 

2、任务如何结束

 自己结束任务:

任务结束后的清除工作:

在创建任务B时候,动态的分配了内存、结构体、栈

在结束任务时候要释放TCB结构体、栈

若是自己结束任务,需要空闲任务来清楚,但若更高优先级的任务都是就绪态,空闲任务无法获取CPU资源执行操作,可能会因无法回收造成内存不足

良好的编程习惯:

  1. 事件驱动(避免一致死循环占用CPU)(比如按下按键才就绪,没按按键就阻塞)
  2. 休眠时不要用死循环,建议替换为阻塞函数

空闲任务的函数

main.c

{启动调度器

{启动调度器

{创建任务

{空闲任务的函数

检查等待中止(自杀)的任务

钩子函数?

四、让当前任务放弃调度的delay函数

Q:各个任务切换任务状态保存在TCB结构体?

Q:任务和线程的关系

关键字:任务状态与调度

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: