zephyr OS 线程的使用

目录

概述

1 线程的概念

1.1 线程定义

 1.2 线程的本质定义

 1.3 线程的核心组成要素

1.4  线程与进程的对比

1.5  线程在RTOS中的关键特性

 1.6 线程的同步与通信

1.7 线程在嵌入式系统的特殊考量

1.8 多线程编程模型

 2  Zephyr RTOS 中线程

2.1 创建线程的步骤

2.2 Zephyr RTOS 中线程定义

2.3 关键API函数

 2.4 线程中的睡眠函数

3  线程应用实践

3.1 完整线程定义模板

3.1.1 源代码

 3.1.2 关键细节

3.2 两个线程交替输出信息


概述

本文主要介绍zephyr OS 线程的使用,在嵌入式RTOS中,合理使用线程是构建高效可靠系统的关键。Zephyr提供了丰富的线程管理API(k_thread_create()k_thread_suspend()等),开发者需根据具体需求平衡线程数量、优先级和资源消耗。

1 线程的概念

1.1 线程定义

线程基础概念

  • 线程状态:就绪(Ready)、挂起(Pending)、运行(Running)、终止(Terminated)

  • 优先级:数值越小优先级越高(0为最高,负数为协程)

  • 调度方式

    • 协作式(Cooperative):线程主动让出CPU(k_yield()

    • 抢占式(Preemptive):高优先级线程抢占低优先级线程

    • 时间片轮转(Round Robin):同优先级线程轮流执行

 1.2 线程的本质定义

线程是:

  • 轻量级进程:比传统进程更小的执行单元

  • 独立执行流:拥有自己的程序计数器、栈和寄存器状态

  • 调度基本单位:操作系统调度的最小单元

  • 资源共享实体:同一进程中的线程共享内存空间和资源

 1.3 线程的核心组成要素

组件 作用 特性
程序计数器(PC) 记录下一条指令地址 线程私有
寄存器集合 存储当前计算状态 线程私有
栈空间 存储局部变量/函数调用链 线程私有
线程控制块(TCB) 存储管理信息(状态、优先级等) 内核管理

1.4  线程与进程的对比

特性 进程 线程
资源分配 独立内存空间 共享进程资源
创建开销 大(MB级) 小(KB级)
切换开销 高(需MMU切换) 低(仅寄存器)
通信方式 IPC(管道、套接字等) 共享内存
容错性 一个崩溃不影响其他 一个崩溃可能影响同进程所有线程

1.5  线程在RTOS中的关键特性

1) 执行状态

  • 就绪(Ready):等待CPU分配

  • 运行(Running):正在CPU执行

  • 阻塞(Blocked):等待事件(I/O、信号量等)

  • 终止(Terminated):执行完成或被终止

2) 优先级机制

  • 固定优先级调度(Zephyr默认)

  • 优先级继承(解决优先级反转)

  • 优先级天花板协议

3)调度策略

类型 特点 适用场景
抢占式 高优先级立即抢占 实时性要求高
协作式 线程主动让出CPU 低功耗系统
时间片轮转 同优先级公平分配 计算密集型

 1.6 线程的同步与通信

 1)关键机制:

-1)互斥锁(Mutex):保护临界区

K_MUTEX_DEFINE(my_mutex);
k_mutex_lock(&my_mutex, K_FOREVER);
// 临界区操作
k_mutex_unlock(&my_mutex);

- 2)信号量(Semaphore):资源计数/同步

-3)消息队列(Message Queue):线程间数据传输

-4) 事件标志(Event Flags):多事件通知

 2)典型问题:

  • 竞态条件:未保护的共享数据访问

  • 死锁:多个线程相互等待资源

  • 优先级反转:低优先级线程阻塞高优先级线程

1.7 线程在嵌入式系统的特殊考量

  1. 栈空间优化

    • 精确计算最大栈深度

    • 使用栈分析工具(如Zephyr的CONFIG_THREAD_ANALYZER

    • 典型大小:512B-4KB(无OS) vs 1-8KB(RTOS)

  2. 实时性保证

    • 最坏执行时间(WCET)分析

    • 中断延迟控制

    • 优先级驱动设计

  3. 资源约束

    • 有限的内存和CPU资源

    • 无MMU情况下的内存保护缺失

    • 低功耗要求(休眠态线程管理)

1.8 多线程编程模型

模型 特点 示例场景
主从模型 主线程分配任务,工作线程执行 传感器数据采集
流水线模型 数据流经多个处理线程 图像处理链路
客户端-服务器 客户端请求,服务器处理 网络通信协议栈
对等模型 线程平等协作 分布式计算

 2  Zephyr RTOS 中线程

2.1 创建线程的步骤

step-1: 定义线程栈

#define THREAD_STACK_SIZE 1024
K_THREAD_STACK_DEFINE(my_thread_stack, THREAD_STACK_SIZE);

step-2:  定义线程结构体

struct k_thread my_thread_data;

 step-3 : 编写线程函数

void my_thread_entry(void *p1, void *p2, void *p3)
{
    while (1) {
        printk("Thread running!\n");
        k_msleep(1000); // 睡眠1秒
    }
}

 step-4:  创建并启动线程

k_tid_t thread_id = k_thread_create(
    &my_thread_data,                // 线程结构体指针
    my_thread_stack,                // 栈空间
    K_THREAD_STACK_SIZEOF(my_thread_stack), // 栈大小
    my_thread_entry,                // 线程入口函数
    NULL, NULL, NULL,               // 入口函数参数(最多3个)
    K_PRIO_COOP(5),                 // 优先级(5,协作式)
    0,                              // 线程选项(通常为0)
    K_NO_WAIT                       // 启动延迟(立即启动)
);

2.2 Zephyr RTOS 中线程定义

1) 线程定义的核心组件

组件 说明 示例
线程控制块 (TCB) 存储线程状态信息 struct k_thread my_thread;
线程栈 分配执行空间 K_THREAD_STACK_DEFINE(my_stack, 1024);
线程函数 线程入口点 void thread_fn(void *a, void *b, void *c) {...}
线程属性 优先级、选项等 K_PRIO_PREEMPT(5), K_FP_REGS

2.3 关键API函数

函数 作用
k_thread_create() 创建并启动线程
k_thread_suspend() 挂起线程
k_thread_resume() 恢复挂起的线程
k_sleep() / k_msleep() 线程睡眠(毫秒/秒)
k_yield() 主动让出CPU
k_thread_join() 等待线程结束
k_thread_abort() 终止线程

 2.4 线程中的睡眠函数

函数 线程状态 恢复条件 适用场景
k_yield() 保持就绪(Ready) 随时可被调度 主动让出 CPU
k_sleep() 进入阻塞(Pending) 超时后恢复 需要延时等待
k_msleep() 进入阻塞(Pending) 超时后恢复 毫秒级延时

3  线程应用实践

3.1 完整线程定义模板

3.1.1 源代码

#include 

/* 1. 定义线程栈 */
#define MY_STACK_SIZE 1024
K_THREAD_STACK_DEFINE(my_thread_stack, MY_STACK_SIZE);

/* 2. 定义线程控制块 */
static struct k_thread my_thread;

/* 3. 线程函数实现 */
void my_thread_entry(void *arg1, void *arg2, void *arg3)
{
    int *param = (int *)arg1;  // 参数转换
    
    while (1) {
        printk("Thread running: %d\n", *param);
        k_msleep(500);
        
        // 协作式线程需要主动让出
        k_yield();
    }
}

/* 4. 创建并启动线程 */
int init_my_thread(void)
{
    int thread_param = 42;  // 传递给线程的参数
    
    k_tid_t tid = k_thread_create(
        &my_thread,                   // 线程控制块
        my_thread_stack,              // 栈空间
        K_THREAD_STACK_SIZEOF(my_thread_stack), // 栈大小
        my_thread_entry,              // 入口函数
        &thread_param, NULL, NULL,    // 参数 (最多3个)
        K_PRIO_PREEMPT(5),           // 优先级 (抢占式)
        0,                           // 线程选项
        K_NO_WAIT                    // 启动延迟
    );
    
    return (tid != NULL) ? 0 : -1;  // 检查创建是否成功
}

 3.1.2 关键细节

1)线程栈定义

// 静态定义(推荐)
K_THREAD_STACK_DEFINE(stack_name, size_in_bytes);

// 动态分配(需启用CONFIG_HEAP_MEM_POOL_SIZE)
k_thread_stack_t *dyn_stack = k_thread_stack_alloc(size, align);

2)线程参数传递

线程入口函数支持最多3个参数:

// 创建时传递参数
k_thread_create(..., 
    (void *)&device,  // arg1
    (void *)&config,  // arg2
    (void *)&status   // arg3
);

// 在线程中访问
void thread_fn(void *arg1, void *arg2, void *arg3)
{
    struct device *dev = (struct device *)arg1;
    struct config *cfg = (struct config *)arg2;
    int *status_flag = (int *)arg3;
}

 

3.2 两个线程交替输出信息

#include 

K_THREAD_STACK_DEFINE(threadA_stack, 512);
K_THREAD_STACK_DEFINE(threadB_stack, 512);
struct k_thread threadA_data, threadB_data;

void threadA(void *, void *, void *) {
    while (1) {
        printk("A");
        k_msleep(100);
    }
}

void threadB(void *, void *, void *) {
    while (1) {
        printk("B");
        k_msleep(100);
    }
}

int main(void) {
    k_thread_create(&threadA_data, threadA_stack,
                    K_THREAD_STACK_SIZEOF(threadA_stack),
                    threadA, NULL, NULL, NULL,
                    5, 0, K_NO_WAIT);

    k_thread_create(&threadB_data, threadB_stack,
                    K_THREAD_STACK_SIZEOF(threadB_stack),
                    threadB, NULL, NULL, NULL,
                    5, 0, K_NO_WAIT);

    return 0;
}

 

你可能感兴趣的:(zephyr OS 线程的使用)