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());
}
构建与运行
- 将上述代码保存为项目主文件(如
src/main.c),替换默认的hello_world示例。 - 在项目根目录的
prj.conf中添加(如无则新建):CONFIG_PRINTK=y - 使用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线程创建完两个线程后主动终止,避免其干扰调度顺序。