zephyr笔记 2.1.1 线程的生命周期

2020-04-17 10:28:53 浏览数 (1)

1 前言

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

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

2 概念

概念不复制了。

3 操作

3.1 Spawning a Thread

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

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

如下是示例代码:

代码语言:javascript复制
#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都自动创建。

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

代码语言:javascript复制
#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

代码语言:javascript复制
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 函数中返回,即可终止线程。

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

代码语言:javascript复制
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

0 人点赞