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