3. 线程优先级实验

线程优先级实验 学习卡片

任务目标

创建两个不同优先级的Zephyr线程,通过日志输出顺序验证高优先级线程会抢占低优先级线程的执行。

实现原理

Zephyr RTOS采用基于优先级的抢占式调度。当高优先级线程就绪时,调度器会立即暂停当前运行的低优先级线程,将CPU分配给高优先级线程。本实验通过两个线程交替打印日志来直观展示这一行为。

完整代码

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>

#define STACK_SIZE 512
#define THREAD_PRIO_LOW  10
#define THREAD_PRIO_HIGH 5

/* 线程栈 */
K_THREAD_STACK_DEFINE(low_stack, STACK_SIZE);
K_THREAD_STACK_DEFINE(high_stack, STACK_SIZE);

/* 线程控制块 */
struct k_thread low_thread;
struct k_thread high_thread;

/* 低优先级线程入口 */
void low_prio_entry(void *arg1, void *arg2, void *arg3)
{
    for (int i = 0; i < 3; i++) {
        printk("[低优先级] 正在执行,迭代 %d\n", i);
        k_msleep(100);  /* 主动让出CPU */
    }
    printk("[低优先级] 执行完毕\n");
}

/* 高优先级线程入口 */
void high_prio_entry(void *arg1, void *arg2, void *arg3)
{
    for (int i = 0; i < 3; i++) {
        printk("[高优先级] 正在执行,迭代 %d\n", i);
        k_msleep(100);
    }
    printk("[高优先级] 执行完毕\n");
}

void main(void)
{
    printk("线程优先级实验开始\n");

    /* 创建低优先级线程 */
    k_thread_create(&low_thread, low_stack, STACK_SIZE,
                    low_prio_entry, NULL, NULL, NULL,
                    THREAD_PRIO_LOW, 0, K_NO_WAIT);

    /* 创建高优先级线程 */
    k_thread_create(&high_thread, high_stack, STACK_SIZE,
                    high_prio_entry, NULL, NULL, NULL,
                    THREAD_PRIO_HIGH, 0, K_NO_WAIT);

    /* main线程退出调度 */
    k_thread_abort(k_current_get());
}

构建与运行

  1. 将上述代码保存为项目主文件(如src/main.c),替换默认的hello_world示例。
  2. 在项目根目录的prj.conf中添加(如无则新建):
    CONFIG_PRINTK=y
  3. 使用west构建并烧录(以qemu_x86为例):
    west build -b qemu_x86
    west build -t run

验证方法

观察串口输出,预期日志顺序为:

线程优先级实验开始
[高优先级] 正在执行,迭代 0
[低优先级] 正在执行,迭代 0
[高优先级] 正在执行,迭代 1
[低优先级] 正在执行,迭代 1
[高优先级] 正在执行,迭代 2
[低优先级] 正在执行,迭代 2
[高优先级] 执行完毕
[低优先级] 执行完毕

判定标准:高优先级线程的日志总是先于低优先级线程输出(在每次迭代中,高优先级先打印),且高优先级线程先完成全部3次迭代。若低优先级线程先运行或两者交替顺序混乱,则说明优先级配置或调度器行为异常。

关键说明

  • Zephyr中数值越小优先级越高,因此THREAD_PRIO_HIGH=5高于THREAD_PRIO_LOW=10。
  • 两个线程均通过k_msleep(100)主动让出CPU,使另一个线程有机会运行;否则高优先级线程会独占CPU,低优先级线程永远无法执行。
  • main线程创建完两个线程后主动终止,避免其干扰调度顺序。