打印
[应用相关]

RTOS是如何实现的,比如任务调度器是如何在几个死循环切换的

[复制链接]
394|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
RTOS是如何实现的,比如任务调度器是如何在几个死循环切换的?
一直不懂,很好奇。

使用特权

评论回复
沙发
xuanhuanzi| | 2025-1-23 15:20 | 只看该作者
RTOS 调度器实现的本质是让这些任务的死循环 “交替运行”

使用特权

评论回复
板凳
xuanhuanzi| | 2025-1-23 15:22 | 只看该作者
#include <stdint.h>
#include <stdio.h>

// 模拟任务堆栈
uint32_t Task1_Stack[128];
uint32_t Task2_Stack[128];

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

TCB Task1_TCB, Task2_TCB;

// 当前任务指针
TCB *CurrentTask;
TCB *NextTask;

// 模拟任务函数
void Task1(void) {
    while (1) {
        printf("Task 1 is running\n");
        // 模拟延时
        for (volatile int i = 0; i < 1000000; i++);
    }
}

void Task2(void) {
    while (1) {
        printf("Task 2 is running\n");
        // 模拟延时
        for (volatile int i = 0; i < 1000000; i++);
    }
}

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

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

    // 设置初始任务
    CurrentTask = &Task1_TCB;
    NextTask = &Task2_TCB;
}

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

    // 切换到下一个任务
    TCB *Temp = CurrentTask;
    CurrentTask = NextTask;
    NextTask = Temp;

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

int main(void) {
    Task_Init();

    while (1) {
        Task_Switch(); // 定期切换任务
    }
}

使用特权

评论回复
地板
xuanhuanzi| | 2025-1-23 15:22 | 只看该作者
上面是一个简单的调度器的实现

使用特权

评论回复
5
江河千里| | 2025-2-8 01:00 | 只看该作者
类似于中断,就是来回嵌套这种

使用特权

评论回复
6
冰春彩落下| | 2025-2-8 02:00 | 只看该作者
其实就是有个定时器,计时每个任务吧

使用特权

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

使用特权

评论回复
8
RTOS中的每个任务都可以处于不同的状态,如就绪态、运行态、阻塞态和挂起态

使用特权

评论回复
9
三生万物| | 2025-2-8 05:00 | 只看该作者
其实RTOS会根据任务的优先级进行排序,高优先级的任务会优先获得处理器资源。当多个任务具有相同优先级时,可能会采用时间片轮转等方式进行调度

使用特权

评论回复
10
淡漠安然| | 2025-2-8 06:00 | 只看该作者
上下文切换是RTOS实现任务切换的关键机制。在上下文切换过程中,RTOS会保存当前任务的运行环境(如寄存器值、堆栈指针等)到其任务栈中

使用特权

评论回复
11
光辉梦境| | 2025-2-8 07:00 | 只看该作者
任务切换通常由以下事件触发,一个正在运行的任务调用阻塞函数(如等待某个事件或资源)

使用特权

评论回复
12
远山寻你| | 2025-2-8 08:00 | 只看该作者
定时器中断或其他系统事件导致任务调度器重新评估任务的优先级和状态

使用特权

评论回复
13
公羊子丹| | 2025-2-8 08:35 | 只看该作者
RTOS的任务切换其实是靠“时钟中断”实现的,每次中断都会保存当前任务的上下文,然后切换到下一个任务。

使用特权

评论回复
14
周半梅| | 2025-2-8 08:36 | 只看该作者
任务调度器的核心就是保存和恢复CPU寄存器状态,类似于快速切换不同的程序现场。

使用特权

评论回复
15
帛灿灿| | 2025-2-8 08:38 | 只看该作者
本帖最后由 帛灿灿 于 2025-2-8 08:39 编辑

其实“死循环”是任务的常态,但调度器中断打断后会强制执行下一个任务,所以看起来像在多个任务间切换。

使用特权

评论回复
16
童雨竹| | 2025-2-8 08:40 | 只看该作者
FreeRTOS中每个任务都有自己的栈空间,切换时就把当前栈指针和任务状态保存起来,下次再恢复。

使用特权

评论回复
17
万图| | 2025-2-8 08:42 | 只看该作者
调度策略一般有两种:时间片轮转和优先级调度,高优先级任务能打断低优先级任务。

使用特权

评论回复
18
Wordsworth| | 2025-2-8 08:43 | 只看该作者
比如一个10ms的时钟中断就可以用来触发调度器,让RTOS以10ms的周期切换任务。

使用特权

评论回复
19
Bblythe| | 2025-2-8 08:44 | 只看该作者
如果不依赖中断,纯软件延时的调度方法效率会非常低,所以硬件定时器很关键。

使用特权

评论回复
20
Pulitzer| | 2025-2-8 08:45 | 只看该作者
初学建议直接看FreeRTOS或者Zephyr的源码,调度器部分逻辑很清晰。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

182

主题

3421

帖子

13

粉丝