4.2.2 任务创建与销毁
2026/7/16大约 6 分钟内核组件内核任务管理任务创建任务销毁
4.2.2 任务创建与销毁
📚 本节导读
学习时长: 约 20 分钟
难度级别: ⭐⭐⭐☆☆
前置知识: 任务控制块(TCB)、任务状态机
🎯 学习目标
- 掌握
os_task_create()的完整参数和返回值 - 理解静态创建与动态创建的区别和使用场景
- 掌握
os_task_startup()和os_task_destroy()的用法 - 了解清理回调和用户数据的作用
一、os_task_create() —— 创建任务
1.1 函数签名
os_task_id os_task_create(os_task_dummy_t *task_cb,
void *stack_begin,
uint32_t stack_size,
const char *name,
void (*entry)(void *arg),
void *arg,
uint8_t priority);1.2 参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
task_cb | os_task_dummy_t * | 任务控制块指针。传入 NULL 表示由内核动态分配 |
stack_begin | void * | 任务栈起始地址。传入 NULL 表示由内核动态分配 |
stack_size | uint32_t | 任务栈大小(字节),必须大于 0 |
name | const char * | 任务名称,最大长度为 OS_NAME_MAX(默认 15 字符) |
entry | void (*)(void *arg) | 任务入口函数指针 |
arg | void * | 传递给入口函数的参数 |
priority | uint8_t | 任务优先级,范围 0 ~ OS_TASK_PRIORITY_MAX - 1(0 最高) |
1.3 返回值
| 返回值 | 说明 |
|---|---|
非 NULL | 任务创建成功,返回任务 ID(即 TCB 指针) |
NULL | 任务创建失败(如内存不足、TCB 已存在) |
1.4 内部工作流程
- 检查参数合法性(
entry != NULL、stack_size > 0、priority < OS_TASK_PRIORITY_MAX) - 如果
task_cb == NULL且启用了OS_USING_HEAP,动态分配 TCB 内存 - 如果
stack_begin == NULL且启用了OS_USING_HEAP,动态分配对齐的栈内存 - 检查静态 TCB 是否已被使用(防止重复创建)
- 将 TCB 加入全局任务资源链表
- 调用
_k_task_init()初始化 TCB 各字段 - 设置任务状态为
OS_TASK_STATE_INIT - 返回任务 ID
注意:
os_task_create()不会在中断上下文中执行,也不应在中断禁用或调度器锁定的情况下调用。
二、静态创建任务
静态创建适用于资源受限、不允许动态内存分配的系统。
2.1 静态创建宏
/* 定义任务控制块 */
#define OS_TASK_DEFINE(name) os_task_dummy_t name
/* 定义任务栈 */
#define OS_TASK_STACK_DEFINE(name, size) \
OS_ALIGN(OS_ARCH_STACK_ALIGN_SIZE) uint8_t (name)[OS_ALIGN_UP(size, OS_ARCH_STACK_ALIGN_SIZE)]
/* 获取栈信息 */
#define OS_TASK_STACK_BEGIN_ADDR(name) (void *)&((name)[0])
#define OS_TASK_STACK_SIZE(name) sizeof(name)2.2 静态创建示例
#include <os_task.h>
/* 步骤 1:定义任务控制块 */
OS_TASK_DEFINE(my_task_cb);
/* 步骤 2:定义任务栈(1024 字节,自动对齐) */
OS_TASK_STACK_DEFINE(my_task_stack, 1024);
/* 步骤 3:任务入口函数 */
void my_task_entry(void *arg)
{
while (1)
{
/* 任务逻辑 */
os_task_msleep(1000);
}
}
/* 步骤 4:创建并启动任务 */
void app_init(void)
{
os_task_id tid;
tid = os_task_create(
&my_task_cb, /* 传入静态 TCB */
OS_TASK_STACK_BEGIN_ADDR(my_task_stack), /* 传入静态栈起始地址 */
OS_TASK_STACK_SIZE(my_task_stack), /* 传入静态栈大小 */
"my_task", /* 任务名称 */
my_task_entry, /* 入口函数 */
OS_NULL, /* 入口参数 */
5 /* 优先级 */
);
if (tid != OS_NULL)
{
os_task_startup(tid); /* 启动任务 */
}
}三、动态创建任务
动态创建适用于内存充足、追求灵活性的场景,需要启用 OS_USING_HEAP。
3.1 动态创建示例
#include <os_task.h>
/* 任务入口函数 */
void my_task_entry(void *arg)
{
int *pdata = (int *)arg;
while (1)
{
/* 任务逻辑 */
os_task_msleep(500);
}
}
/* 创建并启动任务 */
void app_init(void)
{
os_task_id tid;
static int task_param = 42;
/* TCB 和栈都传 NULL,内核自动分配 */
tid = os_task_create(
OS_NULL, /* TCB 由内核自动分配 */
OS_NULL, /* 栈由内核自动分配 */
2048, /* 栈大小 */
"dynamic_task", /* 任务名称 */
my_task_entry, /* 入口函数 */
&task_param, /* 入口参数 */
10 /* 优先级 */
);
if (tid != OS_NULL)
{
os_task_startup(tid);
}
}3.2 混合创建(静态 TCB + 动态栈)
OS_TASK_DEFINE(my_task_cb); /* 静态 TCB */
os_task_id tid = os_task_create(
&my_task_cb, /* 静态 TCB */
OS_NULL, /* 动态分配栈 */
2048, /* 栈大小 */
"hybrid_task",
my_task_entry,
OS_NULL,
5
);四、os_task_startup() —— 启动任务
4.1 函数签名
os_err_t os_task_startup(os_task_id tid);4.2 功能说明
os_task_startup() 将任务从 INIT 状态转为 READY 状态,并将其加入就绪队列。如果新任务的优先级高于当前任务,将立即触发任务切换。
4.3 内部流程
os_err_t os_task_startup(os_task_id tid)
{
/* 断言:任务必须处于 INIT 状态 */
OS_ASSERT(OS_TASK_STATE_INIT == task->state);
/* 状态转换:INIT -> READY */
task->state &= ~OS_TASK_STATE_INIT;
task->state |= OS_TASK_STATE_READY;
/* 加入就绪队列 */
k_readyq_put(task);
/* 触发调度 */
OS_KERNEL_EXIT_SCHED();
return OS_SUCCESS;
}4.4 使用示例
os_task_id tid = os_task_create(...);
if (tid != OS_NULL)
{
os_task_startup(tid); /* 任务开始运行 */
}五、os_task_destroy() —— 销毁任务
5.1 函数签名
os_err_t os_task_destroy(os_task_id tid);5.2 返回值
| 返回值 | 说明 |
|---|---|
OS_SUCCESS | 销毁成功 |
OS_BUSY | 任务持有互斥锁,无法销毁 |
| 其他 | 销毁失败 |
5.3 销毁流程
- 检查任务是否持有互斥锁(持有时返回
OS_BUSY) - 将
object_inited设为OS_KOBJ_DEINITED - 从全局资源链表移除 TCB
- 设置状态为
OS_TASK_STATE_CLOSE - 如果正在销毁的是当前任务(自己销毁自己):
- 将 TCB 加入回收链表
- 唤醒 recycle-task 进行资源回收
- 触发调度,切换到其他任务
- 如果销毁非当前任务:
- 立即释放静态/动态资源
- 如果注册了清理回调,执行清理回调
5.4 使用示例
/* 其他任务销毁 my_task */
os_task_id tid = os_task_get_id("my_task");
if (tid != OS_NULL)
{
os_task_destroy(tid);
}
/* 任务自己销毁自己 */
void self_destroy_task(void *arg)
{
/* 执行一些清理工作 */
os_task_destroy(os_get_current_task());
/* 不会执行到这里 */
}六、清理回调
6.1 os_task_set_cleanup_callback()
os_err_t os_task_set_cleanup_callback(os_task_id tid, void (*cleanup)(void *user_data));清理回调函数在任务被销毁时自动调用,用于执行用户自定义的清理工作(如释放动态分配的资源)。
6.2 使用示例
void my_cleanup(void *user_data)
{
/* 释放任务中动态分配的资源 */
if (user_data != OS_NULL)
{
os_free(user_data);
}
}
void my_task(void *arg)
{
void *buffer = os_malloc(256); /* 动态分配资源 */
/* 注册清理回调,确保资源被释放 */
os_task_set_cleanup_callback(os_get_current_task(), my_cleanup);
while (1)
{
/* 业务逻辑 */
}
}七、用户数据
7.1 os_task_set_user_data() / os_task_get_user_data()
os_err_t os_task_set_user_data(os_task_id tid, void *user_data);
void *os_task_get_user_data(os_task_id tid);这两个函数允许为任务关联任意私有数据,方便在任务间传递上下文信息。
7.2 使用示例
typedef struct {
int sensor_id;
float threshold;
char name[16];
} sensor_ctx_t;
sensor_ctx_t ctx = { .sensor_id = 1, .threshold = 25.0, .name = "temp" };
/* 为任务设置用户数据 */
os_task_set_user_data(tid, &ctx);
/* 在其他地方获取用户数据 */
sensor_ctx_t *pctx = (sensor_ctx_t *)os_task_get_user_data(tid);
if (pctx != OS_NULL)
{
os_kprintf("Sensor: %s, ID: %d\r\n", pctx->name, pctx->sensor_id);
}八、创建与销毁的注意事项
- 不允许在中断上下文中创建/销毁任务:
os_task_create()和os_task_destroy()内部有断言检查 - 静态创建时 TCB 不能重复使用:如果同一个 TCB 地址已经存在,创建会失败
- 销毁持有互斥锁的任务:会返回
OS_BUSY,因为销毁持锁任务可能导致死锁 - 动态创建需要
OS_USING_HEAP:未启用堆管理时,必须传入非 NULL 的 TCB 和栈指针 - 销毁自己:任务可以通过
os_task_destroy(os_get_current_task())销毁自己,但函数不会返回
📝 本节小结
os_task_create() 是 OneOS 任务管理的核心入口函数,支持静态和动态两种创建方式。静态创建使用宏 OS_TASK_DEFINE() 和 OS_TASK_STACK_DEFINE() 预定义 TCB 和栈空间;动态创建传入 NULL 由内核自动分配。创建后需调用 os_task_startup() 启动任务。os_task_destroy() 用于销毁任务,可配合清理回调和用户数据实现资源的安全释放。