Skip to content

时间片调度 — 任务轮流上场

李述铜

878字约3分钟

2025-08-30

本课时主要介绍RT-Thtread中的时间片调度工作机制,通过示例演示多个同优先级任务如何依靠时间片公平执行。

注:学习本课时时,可复习第3章中的相关内容。


主要原理

基本概念

在多任务操作系统中,如果,该如何让它们公平地使用CPU呢?这就需要用到时间片轮转调度。

就像多人轮流演讲,每个人讲一段时间就交给下一个人,系统通过“时间片”轮流让任务上台执行。

alt text

相关信息

时间片轮转调度是操作系统中常用的任务调度策略,尤其适用于同优先级任务的公平调度。该策略的核心思想是让每个任务轮流执行固定的时间片段(时间片),超时后强制切换任务,防止单一任务长时间独占 CPU。

例如,对于下图中,任务0-2各自都有相同长度的时间片支持其运行。

alt text

系统节拍

在RT-Thread中,每个任务的时间片长度可以不同。该参数在rt_thread_create()或rt_thread_create()调用时指定,即指定任务的时间片为多少个系统节拍。

在RT-Thread中,系统默认每经过一定时间(如 1 毫秒)就会产生一次定时器中断。该定时中断用来驱动RTOS内核的调度器和时间相关的功能。

alt text 该定时器的中断时间间隔由以下配置宏来决定:

#define RT_TICK_PER_SECOND  1000

示例代码:两个任务轮流打印

下面的代码展示了两个相同优先级任务轮流打印的示例代码。

#include <rtthread.h>
#include "base.h"

void task1_entry(void *param) {
    RT_UNUSED(param);

    while (1) {
        rt_kprintf("Task 1 is running\n");
        // 忙等待模拟工作
        for (int i = 0; i < 100000; i++);
    }
}

void task2_entry(void *param) {
    RT_UNUSED(param);

    while (1) {
        rt_kprintf("Task 2 is running\n");
        for (int i = 0; i < 100000; i++);
    }
}

int main(void) {
    hardware_init();

    rt_thread_t t1 = rt_thread_create(
        "t1",
        task1_entry,
        RT_NULL,
        1024,
        10,     // 相同优先级
        20       // 时间片为5个tick
    );

    rt_thread_t t2 = rt_thread_create(
        "t2",
        task2_entry,
        RT_NULL,
        1024,
        10,     // 相同优先级
        40
    );

    if (t1) rt_thread_startup(t1);
    if (t2) rt_thread_startup(t2);

    return 0;
}

上述代码的运行效果如下图所示。仔细分析可以发现,任务1的代码打印数量比任务2的要少,大约是1/2(不一定准确)。

alt text

之所以如此,是因为RT-Thread按时间片来控制两个任务交替占用CPU运行其代码,从而让两个任务都有运行的机会。

此外,由于t1的时间片为20个tick,t2为40个tick;因此,t2每次最大运行的时间为t1的倍。如下图所示。

alt text

总结

  • 时间片调度用于相同优先级的任务之间,实现公平轮流执行
  • 每个任务被分配一个固定时间片
  • 时间片用完后,调度器切换到下一个就绪任务
  • 如果任务进入阻塞状态,会提前让出 CPU

注意事项

时间片仅起到约束线程,任务每次运行的时间可以小于该时间片。