任务是 OneOS 操作系统中最小的调度单位,任务调度算法是基于优先级的抢占式调度算法,即在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的。可支持 256 个任务优先级(可通过配置文件更改为32个或8个优先级),0 优先级代表最高优先级,最低优先级留给空闲任务使用;同时它也支持创建多个具有相同优先级的任务,相同优先级的任务间采用时间片轮转进行调度。系统不限制任务数量的多少。
OneOS 任务管理的主要功能是对任务进行管理和调度,当任务创建时,会从内核对象容器中分配任务对象,当任务被删除时,会从对象容器中删除,如图所示,每个任务都有重要的属性,如任务控制块、任务栈、入口函数等。
任务控制块包含了任务的一些重要信息,如任务优先级、状态、栈信息以及与其他任务或数据结构之间的关系等。其定义如下:
struct os_task
{
os_object_t parent; /* os object */
os_list_node_t task_list; /* the task list */
/* stack point and entry */
void *sp; /* stack point */
void *entry; /* entry */
void *parameter; /* parameter */
void *stack_addr; /* stack address */
os_uint32_t stack_size; /* stack size */
os_err_t error; /* error code */
os_uint8_t stat; /* task status */
/* priority */
os_uint8_t current_priority; /* current priority */
os_uint8_t init_priority; /* initialized priority */
#if OS_TASK_PRIORITY_MAX > 32
os_uint8_t number;
os_uint8_t high_mask;
#endif
os_uint32_t number_mask;
#if defined(OS_USING_EVENT)
/* task event */
os_uint32_t event_set;
os_uint8_t event_info;
#endif
os_ubase_t init_tick; /* task's initialized tick */
os_ubase_t remaining_tick; /* remaining tick */
os_timer_t task_timer; /* built-in task timer */
void (*cleanup)(struct os_task *task); /* cleanup function when task exit */
os_uint32_t user_data; /* private user data beyond this task */
};
任务控制块重要参数 | 说明 |
---|---|
task_list | 任务链表,用于维护与其他任务及数据结构的关系 |
sp | 任务栈指针 |
entry | 任务入口函数 |
parameter | 任务入口函数参数 |
stack_addr | 任务栈起始地址 |
stack_size | 任务栈大小 |
stat | 任务状态 |
current_priority | 任务当前优先级,某些情况下会动态调整任务的优先级 |
init_priority | 任务初始优先级,用于优先级调度算法 |
init_tick | 任务的初始tick,用于在相同优先级任务间的时间片轮转调度算法 |
remaining_tick | 任务的剩余tick,用于在相同优先级任务间的时间片轮转调度算法 |
接口 | 说明 |
---|---|
os_task_init | 任务静态方式初始化,即任务对象由使用者提供 |
os_task_deinit | 任务反初始化,与os_task_init()匹配使用 |
os_task_create | 任务动态创建,要求系统支持内存动态申请,与os_task_init()达到的效果一样,区别在于内存是动态申请的 |
os_task_destroy | 任务动态销毁,与os_task_create()匹配使用 |
os_task_startup | 开启任务执行 |
os_task_self | 获取当前任务的句柄 |
os_task_name | 根据任务句柄获取任务的名字 |
os_task_find | 根据任务名字获取任务句柄 |
os_task_yield | 任务主动放弃CPU的执行权 |
os_task_control | 控制或更改任务的行为属性 |
os_task_sleep | 让当前任务进入睡眠状态,以节拍为单位,不可以在中断上下文使用 |
os_task_msleep | 让当前任务进入睡眠状态,以ms为单位,不可以在中断上下文使用 |
os_task_delay | 与os_task_sleep()一致 |
os_task_mdelay | 与os_task_msleep()一致 |
os_enter_critical | 获得调度锁,进入关键代码区域,停止任务调度 |
os_exit_critical | 释放调度锁,离开关键代码区域,恢复任务调度 |
os_critical_level | 获得调度锁嵌套层次,若为0则代表调度锁已经被释放 |
该函数用于以静态方式初始化任务,其任务句柄(任务控制块指针)、任务栈所对应的空间由使用者提供。任务控制块、任务运行栈一般都设置为全局变量,在编译时就被确定、被分配处理,内核不负责分配其内存空间。其函数原型如下:
os_err_t os_task_init(os_task_t *task,
const char *name,
void (*entry)(void *parameter),
void *parameter,
void *stack_start,
os_uint32_t stack_size,
os_uint8_t priority,
os_uint32_t tick);
参数 | 说明 |
---|---|
task | 任务句柄,由用户提供,并指向对应的任务控制块内存地址 |
name | 任务名称,其最大长度由 oneos_config.h 中定义的OS_NAME_MAX 宏指定,多余部分会被自动截掉 |
entry | 任务入口函数 |
parameter | 任务入口函数参数 |
stack_start | 任务栈起始地址 |
stack_size | 任务栈大小,单位是字节。在大多数系统中需要做栈空间地址对齐 |
priority | 任务的优先级。优先级范围根据系统配置情况(oneos_config.h 中的 OS_TASK_PRIORITY_MAX宏定义)确定,如果支持的是256级优先级,那么范围是从0 ~ 255,数值越小优先级越高,0为最高优先级 |
tick | 任务的时间片大小。时间片(tick)的单位是操作系统的时钟节拍,当系统中存在相同优先级任务时,这个参数指定任务一次调度能够运行的最大时间长度 |
返回 | 说明 |
OS_EOK | 任务创建成功 |
OS_ERROR | 任务创建失败 |
OS_EINVAL | 无效参数 |
该函数用于对静态任务反初始化,与os_task_init()匹配使用,函数原型如下:
os_err_t os_task_deinit(os_task_t *task);
参数 | 说明 |
---|---|
task | 任务句柄,是由 os_task_init() 初始化的任务句柄。 |
返回 | 说明 |
OS_EOK | 成功 |
OS_ERROR | 失败 |
该函数用于以动态方式创建并初始化任务,系统会从内存堆中分配一个任务控制块,按照参数中指定的栈大小从内存堆中分配相应的栈空间,然后初始化参数。函数原型如下:
os_task_t *os_task_create(const char *name,
void (*entry)(void *parameter),
void *parameter,
os_uint32_t stack_size,
os_uint8_t priority,
os_uint32_t tick);
参数 | 说明 |
---|---|
name | 任务名称,最大长度由 oneos_config.h 中的宏 OS_NAME_MAX 指定 |
entry | 任务入口函数 |
parameter | 任务入口函数参数 |
stack_size | 任务栈大小,单位是字节 |
priority | 任务优先级。优先级范围根据系统配置情况(oneos_config.h 中的 OS_TASK_PRIORITY_MAX 宏定义)确定,如果支持的是256 级优先级,那么范围是从0~255,数值越小优先级越高,0为最高优先级 |
tick | 任务时间片大小。时间片(tick)的单位是操作系统的时钟节拍,当系统中存在相同优先级任务时,这个参数指定任务一次调度能够运行的最大时间长度 |
返回 | 说明 |
非OS_NULL | 任务创建成功,返回任务句柄 |
OS_NULL | 任务创建失败 |
该函数用于销毁动态任务,与os_task_create()匹配使用,其函数原型如下:
os_err_t os_task_destroy(os_task_t *task);
参数 | 说明 |
---|---|
task | 要销毁的任务句柄,是由os_task_create()初始化的任务句柄 |
返回 | 说明 |
OS_EOK | 销毁任务成功 |
OS_ERROR | 销毁任务失败 |
该函数可以在任务初始化或者创建成功后,让该任务进入就绪态,如果该任务优先级比当前运行的任务优先级高,会立即切换到该任务运行,其函数原型如下:
os_err_t os_task_startup(os_task_t *task);
参数 | 说明 |
---|---|
task | 任务句柄 |
返回 | 说明 |
OS_EOK | 任务启动成功 |
OS_ERROR | 任务启动失败 |
在系统运行时,该函数用于获取当前任务的句柄,其函数原型如下:
os_task_t *os_task_self(void);
参数 | 说明 |
---|---|
无 | 无 |
返回 | 说明 |
os_task_t * | 任务句柄 |
该函数用于根据任务句柄获取任务的名字,其函数原型如下:
char *os_task_name(os_task_t *task);
参数 | 说明 |
---|---|
task | 任务句柄 |
返回 | 说明 |
char * | 任务名字 |
该函数用于根据任务名字获取任务句柄,该函数原型如下:
os_task_t *os_task_find(char *name);
参数 | 说明 |
---|---|
name | 任务名字 |
返回 | 说明 |
非OS_NULL | 任务句柄 |
OS_NULL | 未找到该任务 |
使用该函数时,当前任务首先把自己从当前所在的就绪优先级任务队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行任务上下文切换,其函数原型如下:
os_err_t os_task_yield(void);
参数 | 说明 |
---|---|
无 | 无 |
返回 | 说明 |
OS_EOK | 成功 |
该函数用于控制或更改任务的行为属性,arg参数含义随着cmd的变化而变化,其函数原型如下:
os_err_t os_task_control(os_task_t *task, enum os_task_ctrl_cmd cmd, void *arg);
参数 | 说明 |
---|---|
task | 任务句柄 |
cmd | 控制命令,包括以下几种:OS_TASK_CTRL_CHANGE_PRIORITY / OS_TASK_CTRL_STARTUP / OS_TASK_CTRL_CLOSE |
arg | 当命令为OS_TASK_CTRL_CHANGE_PRIORITY,此参数表示任务的新优先级 |
返回 | 说明 |
OS_EOK | 更改成功 |
OS_ERROR | 更改失败 |
让当前任务进入睡眠状态,以节拍为单位,不可以在中断上下文使用,其函数原型如下:
os_err_t os_task_sleep(os_tick_t tick);
参数 | 说明 |
---|---|
tick | 任务睡眠的时间,以tick为单位 |
返回 | 说明 |
OS_EOK | 执行成功 |
让当前任务进入睡眠状态,以ms为单位,不可以在中断上下文使用,其函数原型如下:
os_err_t os_task_msleep(os_uint32_t ms);
参数 | 说明 |
---|---|
ms | 任务睡眠的时间,以ms为单位 |
返回 | 说明 |
OS_EOK | 执行成功 |
让当前任务进入睡眠状态,以节拍为单位,不可以在中断上下文使用,其函数原型如下:
os_err_t os_task_delay(os_tick_t tick);
参数 | 说明 |
---|---|
tick | 任务睡眠的时间,以tick为单位 |
返回 | 说明 |
OS_EOK | 执行成功 |
让当前任务进入睡眠状态,以ms为单位,不可以在中断上下文使用,其函数原型如下:
os_err_t os_task_mdelay(os_uint32_t ms);
参数 | 说明 |
---|---|
ms | 任务睡眠的时间,以ms为单位 |
返回 | 说明 |
OS_EOK | 执行成功 |
获得调度锁,进入关键代码区域,停止任务调度,其函数原型如下:
void os_enter_critical(void);
释放调度锁,离开关键代码区域,调度锁嵌套层次为0时恢复任务调度,其函数原型如下:
void os_exit_critical(void);
获得调度锁嵌套层次,若为0则代表调度锁已经被释放,其函数原型如下:
os_uint16_t os_critical_level(void);
参数 | 说明 |
---|---|
无 | 无 |
返回 | 说明 |
os_uint16_t | 当前调度嵌套的深度 |
本例会初始化静态任务并运行,之后再反初始化该任务
#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#define TEST_TASK_TAG "TEST_TASK"
#define TEST_TASK_STACK_SIZE 1024
static os_uint8_t task_static_stack[TEST_TASK_STACK_SIZE];
static os_task_t task_static;
void static_task_entry(void *para)
{
os_uint8_t count = 0;
while (1)
{
LOG_W(TEST_TASK_TAG, "static_task_entry is running, count:%d", count++);
os_task_sleep(100);
}
}
void staic_task_sample(void)
{
os_err_t ret;
ret = os_task_init(&task_static,
"task_static",
static_task_entry,
OS_NULL,
&task_static_stack[0],
TEST_TASK_STACK_SIZE,
15,
10);
if (OS_EOK != ret)
{
LOG_E(TEST_TASK_TAG, "os_task_init fail");
return;
}
LOG_W(TEST_TASK_TAG, "staic_task_sample startup");
os_task_startup(&task_static);
os_task_sleep(500);
LOG_W(TEST_TASK_TAG, "staic_task_sample deinit");
os_task_deinit(&task_static);
}
SH_CMD_EXPORT(static_task, staic_task_sample, "test task init and deinit");
运行结果如下:
sh />static_task
W/TEST_TASK: staic_task_sample startup
W/TEST_TASK: static_task_entry is running, count:0
W/TEST_TASK: static_task_entry is running, count:1
W/TEST_TASK: static_task_entry is running, count:2
W/TEST_TASK: static_task_entry is running, count:3
W/TEST_TASK: static_task_entry is running, count:4
W/TEST_TASK: staic_task_sample deinit
本例会动态创建任务并运行,之后再销毁该任务
#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#define TEST_TASK_TAG "TEST_TASK"
#define TEST_TASK_STACK_SIZE 1024
static os_task_t *task_dynamic = OS_NULL;
void dynamic_task_entry(void *para)
{
os_uint8_t count = 0;
while (1)
{
LOG_W(TEST_TASK_TAG, "dynamic_task_entry is running, count:%d", count++);
os_task_sleep(100);
}
}
void dynamic_task_sample(void)
{
task_dynamic = os_task_create("task_dynamic",
dynamic_task_entry,
OS_NULL,
TEST_TASK_STACK_SIZE,
15,
10);
if (!task_dynamic)
{
LOG_E(TEST_TASK_TAG, "os_task_init fail");
return;
}
LOG_W(TEST_TASK_TAG, "dynamic_task_sample startup");
os_task_startup(task_dynamic);
os_task_sleep(500);
LOG_W(TEST_TASK_TAG, "dynamic_task_sample destroy");
os_task_destroy(task_dynamic);
}
SH_CMD_EXPORT(dynamic_task, dynamic_task_sample, "test task create and destroy");
其运行结果如下:
sh />dynamic_task
W/TEST_TASK: dynamic_task_sample startup
W/TEST_TASK: dynamic_task_entry is running, count:0
W/TEST_TASK: dynamic_task_entry is running, count:1
W/TEST_TASK: dynamic_task_entry is running, count:2
W/TEST_TASK: dynamic_task_entry is running, count:3
W/TEST_TASK: dynamic_task_entry is running, count:4
W/TEST_TASK: dynamic_task_sample destroy
本例利用命令来启动任务、关闭任务、调整优先级等
#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#define TEST_TASK_TAG "TEST_TASK"
#define TEST_TASK_STACK_SIZE 1024
static os_uint8_t task_control_stack[TEST_TASK_STACK_SIZE];
static os_task_t task_control;
void task_control_entry(void *para)
{
os_task_t *task;
char *name;
os_uint8_t count = 0;
while (1)
{
task = os_task_self();
if (task)
{
name = os_task_name(task);
LOG_W(TEST_TASK_TAG, "task %s is running, count:%d", name, count++);
}
os_task_sleep(100);
}
}
void control_task_sample(void)
{
os_err_t ret;
os_uint8_t priority;
priority = 15;
ret = os_task_init(&task_control,
"task_control",
task_control_entry,
OS_NULL,
task_control_stack,
TEST_TASK_STACK_SIZE,
priority,
10);
if (OS_EOK != ret)
{
LOG_E(TEST_TASK_TAG, "os_task_init fail");
return;
}
LOG_W(TEST_TASK_TAG, "control_task_sample startup");
ret = os_task_control(&task_control,OS_TASK_CTRL_STARTUP,OS_NULL);
if (OS_EOK != ret)
{
LOG_E(TEST_TASK_TAG, "start up task fail:%d",ret);
}
os_task_sleep(500);
LOG_W(TEST_TASK_TAG, "control_task_sample change priority");
priority = 19;
ret = os_task_control(&task_control,OS_TASK_CTRL_CHANGE_PRIORITY,&priority);
if (OS_EOK != ret)
{
LOG_E(TEST_TASK_TAG, "change task priority fail:%d",ret);
}
os_task_sleep(500);
LOG_W(TEST_TASK_TAG, "control_task_sample close");
ret = os_task_control(&task_control,OS_TASK_CTRL_CLOSE,OS_NULL);
if (OS_EOK != ret)
{
LOG_E(TEST_TASK_TAG, "close task fail:%d",ret);
}
}
SH_CMD_EXPORT(control_task, control_task_sample, "test task control");
其运行结果如下:
sh />control_task
W/TEST_TASK: control_task_sample startup
W/TEST_TASK: task task_control is running, count:0
W/TEST_TASK: task task_control is running, count:1
W/TEST_TASK: task task_control is running, count:2
W/TEST_TASK: task task_control is running, count:3
W/TEST_TASK: task task_control is running, count:4
W/TEST_TASK: control_task_sample change priority
W/TEST_TASK: task task_control is running, count:5
W/TEST_TASK: task task_control is running, count:6
W/TEST_TASK: task task_control is running, count:7
W/TEST_TASK: task task_control is running, count:8
W/TEST_TASK: task task_control is running, count:9
W/TEST_TASK: control_task_sample close