zephyr笔记 2.1.1 线程的生命周期

我正在学习 Zephyr,一个很可能会用到很多物联网设备上的操作系统,如果你也感兴趣,可点此查看帖子zephyr学习笔记汇总

1 前言

这节将会描述线程的创建,调度以及删除操作。

http://docs.zephyrproject.org/kernel/threads/lifecycle.html

2 概念

概念不复制了。

3 操作

3.1 Spawning a Thread

线程的创建,是通过定义它的栈区域,以及它的线程控制块,之后调用 k_thread_create()。其中的栈区域是通过 K_THREAD_STACK_DEFINE 来定义,保证在内存中建立起区域。

线程创建函数将会返回它的线程id,以此来对应线程。

如下是示例代码:

#define MY_STACK_SIZE 500
#define MY_PRIORITY 5

extern void my_entry_point(void *, void *, void *);

K_THREAD_STACK_DEFINE(my_stack_area, MY_STACK_SIZE);
struct k_thread my_thread_data;

k_tid_t my_tid = k_thread_create(&my_thread_data, my_stack_area,
                                 K_THREAD_STACK_SIZEOF(my_stack_area),
                                 my_entry_point,
                                 NULL, NULL, NULL,
                                 MY_PRIORITY, 0, K_NO_WAIT);

Alternatively, a thread can be spawned at compile time by calling K_THREAD_DEFINE. Observe that the macro defines the stack area, control block, and thread id variables automatically.
或者,线程可以在编译时间通过调用 K_THREAD_DEFINE 来创建,栈区域、控制块、线程id都自动创建。

如下代码和上面的代码是一样的:

#define MY_STACK_SIZE 500
#define MY_PRIORITY 5

extern void my_entry_point(void *, void *, void *);

K_THREAD_DEFINE(my_tid, MY_STACK_SIZE,
                my_entry_point, NULL, NULL, NULL,
                MY_PRIORITY, 0, K_NO_WAIT);

用户模式限制

这节仅适用于 CONFIG_USERSPACE 使能,用户线程想要创建新线程的情况。仍可以使用 k_thread_create() API,但有一些额外的限制需要注意下,否则调用会被停止:

  • The calling thread must have permissions granted on both the child thread and stack parameters; both are tracked by the kernel as kernel objects.
  • The child thread and stack objects must be in an uninitialized state, i.e. it is not currently running and the stack memory is unused.
  • The stack size parameter passed in must be equal to or less than the bounds of the stack object when it was declared.
  • The K_USER option must be used, as user threads can only create other user threads.
  • The K_ESSENTIAL option must not be used, user threads may not be considered essential threads.
  • The priority of the child thread must be a valid priority value, and equal to or lower than the parent thread.

3.2 Dropping Permissions

If CONFIG_USERSPACE is enabled, a thread running in supervisor mode may perform a one-way transition to user mode using the k_thread_user_mode_enter() API. This is a one-way operation which will reset and zero the thread’s stack memory. The thread will be marked as non-essential.

3.3 终止线程

线程可以从自己的 entry point 函数中返回,即可终止线程。

如下代码展示如何终止线程。

void my_entry_point(int unused1, int unused2, int unused3)
{
    while (1) {
        ...
        if (<some condition>) {
            return; /* thread terminates from mid-entry point function */
        }
        ...
    }

    /* thread terminates at end of entry point function */
}

如果 CONFIG_USERSPACE 使能,终止一个线程将会标记线程和栈为未初始化,以方便他们再次使用。

4 建议用法

使用线程来处理那些不能在ISR的事务。

使用分开的线程来处理逻辑上分开又可以并行的操作。

5 配置选项

  • CONFIG_USERSPACE

6 API

下列线程API,都在 kernel.h 中提供了:

K_THREAD_DEFINE
k_thread_create()
k_thread_cancel()
k_thread_abort()
k_thread_suspend()
k_thread_resume()
K_THREAD_STACK_DEFINE
K_THREAD_STACK_ARRAY_DEFINE
K_THREAD_STACK_MEMBER
K_THREAD_STACK_SIZEOF
K_THREAD_STACK_BUFFER

End


<think>我们在Zephyr RTOS中获取当前线程的方法是使用内核提供的API函数。根据Zephyr文档,我们可以使用`k_current_get()`函数来获取当前线程的指针。这个函数返回一个指向当前正在执行的线程的`k_tid_t`类型的线程ID。 下面是一个简单的示例代码,展示如何在Zephyr应用程序中获取当前线程: ```c #include <zephyr/kernel.h> void my_function(void) { // 获取当前线程线程ID k_tid_t current_thread = k_current_get(); // 现在current_thread就是指向当前线程结构的指针 // 我们可以用它来访问线程的信息,例如: // current_thread->name (线程名称) // current_thread->base.prio (线程优先级) } ``` 注意:`k_current_get()`是一个内联函数,它直接返回当前线程的指针。在多线程环境中,这个函数返回的是当前CPU核心正在执行的线程的指针。 另外,需要注意的是,在Zephyr中,线程控制块(thread control block)是一个内部结构(`struct k_thread`),我们通常不需要直接访问其内部成员,除非有特殊需求。如果需要获取线程的信息,最好使用Zephyr提供的其他API(例如获取线程优先级、线程状态等)。 引用[2]中提到,调度程序确定当前执行的线程,而`k_current_get()`正是获取这个当前线程。 因此,总结来说,在Zephyr中获取当前线程的方法是调用`k_current_get()`函数。 §§相关问题§§ 1. Zephyr中如何获取当前线程的名称? 2. Zephyr中如何获取当前线程的优先级? 3. Zephyr中如何判断当前线程是抢占式线程还是协作式线程? </think>在Zephyr RTOS中获取当前线程的方法是通过API函数`k_current_get()`实现,该函数返回当前执行线程线程ID(`k_tid_t`类型)。以下是具体说明和使用示例: ### 获取当前线程的方法 ```c #include <zephyr/kernel.h> void get_current_thread(void) { // 获取当前线程ID k_tid_t current_thread = k_current_get(); // 可通过线程ID访问线程属性 printk("当前线程优先级: %d\n", k_thread_priority_get(current_thread)); } ``` ### 关键特性说明 1. **返回值类型** `k_current_get()`返回`k_tid_t`(线程标识符),本质是指向线程控制块(`struct k_thread`)的指针。 2. **线程调度关联** 当前线程由调度器在调度点动态确定,调用`k_current_get()`始终返回当前CPU核心正在执行的线程[^2]。 3. **优先级识别** 结合引用[1]的优先级规则: ```c int priority = k_thread_priority_get(k_current_get()); if(priority < 0) { printk("协作线程 (优先级%d)\n", priority); } else { printk("抢占线程 (优先级%d)\n", priority); } ``` 4. **唤醒机制关联** 获取的线程ID可用于`k_wakeup()`唤醒操作,但需注意仅对休眠线程有效(引用[4])。 ### 典型应用场景 - 调试中记录当前线程信息 - 实现线程间同步时验证调用者身份 - 动态调整线程优先级(需配合`k_thread_priority_set()`)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值