[应用相关] RTOS是如何实现的,比如任务调度器是如何在几个死循环切换的

[复制链接]
 楼主| 天灵灵地灵灵 发表于 2025-1-23 15:19 | 显示全部楼层 |阅读模式
RTOS是如何实现的,比如任务调度器是如何在几个死循环切换的?
一直不懂,很好奇。
xuanhuanzi 发表于 2025-1-23 15:20 | 显示全部楼层
RTOS 调度器实现的本质是让这些任务的死循环 “交替运行”
xuanhuanzi 发表于 2025-1-23 15:22 | 显示全部楼层
  1. #include <stdint.h>
  2. #include <stdio.h>

  3. // 模拟任务堆栈
  4. uint32_t Task1_Stack[128];
  5. uint32_t Task2_Stack[128];

  6. // 模拟任务控制块 (TCB)
  7. typedef struct {
  8.     uint32_t *StackPointer; // 堆栈指针
  9.     uint32_t Priority;      // 任务优先级
  10. } TCB;

  11. TCB Task1_TCB, Task2_TCB;

  12. // 当前任务指针
  13. TCB *CurrentTask;
  14. TCB *NextTask;

  15. // 模拟任务函数
  16. void Task1(void) {
  17.     while (1) {
  18.         printf("Task 1 is running\n");
  19.         // 模拟延时
  20.         for (volatile int i = 0; i < 1000000; i++);
  21.     }
  22. }

  23. void Task2(void) {
  24.     while (1) {
  25.         printf("Task 2 is running\n");
  26.         // 模拟延时
  27.         for (volatile int i = 0; i < 1000000; i++);
  28.     }
  29. }

  30. // 初始化任务
  31. void Task_Init(void) {
  32.     // 初始化 Task1 堆栈和控制块
  33.     Task1_TCB.StackPointer = &Task1_Stack[127];  // 设置栈顶
  34.     *Task1_TCB.StackPointer-- = (uint32_t)Task1; // 设置 PC 为 Task1 函数地址

  35.     // 初始化 Task2 堆栈和控制块
  36.     Task2_TCB.StackPointer = &Task2_Stack[127];
  37.     *Task2_TCB.StackPointer-- = (uint32_t)Task2;

  38.     // 设置初始任务
  39.     CurrentTask = &Task1_TCB;
  40.     NextTask = &Task2_TCB;
  41. }

  42. // 模拟任务切换
  43. void Task_Switch(void) {
  44.     // 保存当前任务上下文
  45.     __asm volatile ("PUSH {R0-R12, LR}");

  46.     // 切换到下一个任务
  47.     TCB *Temp = CurrentTask;
  48.     CurrentTask = NextTask;
  49.     NextTask = Temp;

  50.     // 恢复下一个任务上下文
  51.     __asm volatile ("POP {R0-R12, LR}");
  52.     __asm volatile ("BX LR");
  53. }

  54. int main(void) {
  55.     Task_Init();

  56.     while (1) {
  57.         Task_Switch(); // 定期切换任务
  58.     }
  59. }
xuanhuanzi 发表于 2025-1-23 15:22 | 显示全部楼层
上面是一个简单的调度器的实现
江河千里 发表于 2025-2-8 01:00 | 显示全部楼层
类似于中断,就是来回嵌套这种

冰春彩落下 发表于 2025-2-8 02:00 | 显示全部楼层
其实就是有个定时器,计时每个任务吧

别乱了阵脚 发表于 2025-2-8 03:00 | 显示全部楼层
RTOS(实时操作系统)的实现涉及多个复杂的机制,其中任务调度器是关键组件之一。任务调度器负责在多个任务之间切换,确保每个任务都能获得必要的处理器时间,从而满足实时性要求。在RTOS中,任务通常是以死循环的形式存在的,但任务调度器能够确保这些任务在看似同时运行的情况下轮流获得CPU的控制权

暖了夏天蓝了海 发表于 2025-2-8 04:00 | 显示全部楼层
RTOS中的每个任务都可以处于不同的状态,如就绪态、运行态、阻塞态和挂起态

三生万物 发表于 2025-2-8 05:00 | 显示全部楼层
其实RTOS会根据任务的优先级进行排序,高优先级的任务会优先获得处理器资源。当多个任务具有相同优先级时,可能会采用时间片轮转等方式进行调度

淡漠安然 发表于 2025-2-8 06:00 | 显示全部楼层
上下文切换是RTOS实现任务切换的关键机制。在上下文切换过程中,RTOS会保存当前任务的运行环境(如寄存器值、堆栈指针等)到其任务栈中

光辉梦境 发表于 2025-2-8 07:00 | 显示全部楼层
任务切换通常由以下事件触发,一个正在运行的任务调用阻塞函数(如等待某个事件或资源)

远山寻你 发表于 2025-2-8 08:00 | 显示全部楼层
定时器中断或其他系统事件导致任务调度器重新评估任务的优先级和状态

公羊子丹 发表于 2025-2-8 08:35 | 显示全部楼层
RTOS的任务切换其实是靠“时钟中断”实现的,每次中断都会保存当前任务的上下文,然后切换到下一个任务。
周半梅 发表于 2025-2-8 08:36 | 显示全部楼层
任务调度器的核心就是保存和恢复CPU寄存器状态,类似于快速切换不同的程序现场。
帛灿灿 发表于 2025-2-8 08:38 | 显示全部楼层
本帖最后由 帛灿灿 于 2025-2-8 08:39 编辑

其实“死循环”是任务的常态,但调度器中断打断后会强制执行下一个任务,所以看起来像在多个任务间切换。
童雨竹 发表于 2025-2-8 08:40 | 显示全部楼层
FreeRTOS中每个任务都有自己的栈空间,切换时就把当前栈指针和任务状态保存起来,下次再恢复。
万图 发表于 2025-2-8 08:42 | 显示全部楼层
调度策略一般有两种:时间片轮转和优先级调度,高优先级任务能打断低优先级任务。
Wordsworth 发表于 2025-2-8 08:43 | 显示全部楼层
比如一个10ms的时钟中断就可以用来触发调度器,让RTOS以10ms的周期切换任务。
Bblythe 发表于 2025-2-8 08:44 | 显示全部楼层
如果不依赖中断,纯软件延时的调度方法效率会非常低,所以硬件定时器很关键。
Pulitzer 发表于 2025-2-8 08:45 | 显示全部楼层
初学建议直接看FreeRTOS或者Zephyr的源码,调度器部分逻辑很清晰。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

182

主题

3469

帖子

13

粉丝
快速回复 在线客服 返回列表 返回顶部