现代操作系统都建立在任务的基础上,任务是AliOS Things的一个基本执行环境,有的操作系统也称之为线程(thread)。多任务的运行环境提供了一个基本机制,从宏观上可以看作单个CPU执行单元上同时执行多个任务,从微观上看,CPU快速地切换任务来并发运行多个任务。AliOS Things实时操作系统支持多任务机制。

每个任务都具有上下文(context),上下文context是指当任务被调度执行的时候此任务能看见的CPU资源和系统资源,当发生任务切换的时候,任务的上下文被保存在任务控制块(ktask_t)中,这些上下文包括当前任务的CPU指令地址(PC指针),当前任务的栈空间,当前任务的CPU寄存器状态等。

任务管理功能的相关源码位于:/core/osal/aos/rhino.c 文件中(AliOS Things v3.1);osal/aos/rhino.c(AliOS Things v3.0及以前)。

API列表

aos_task_new() 动态创建一个任务,任务句柄不返回,创建完后自动运行
aos_task_new_ext() 动态创建一个任务,传入任务句柄,并指定优先级,创建完后自动运行
aos_task_exit() 任务自动退出
aos_task_delete() 任务删除
aos_task_name() 返回当前任务名
aos_task_key_create() 申请一个任务私有数据区域
aos_task_key_delete() 释放一个任务私有数据区域
aos_task_setspecific() 设置指定任务私有数据区域的内容
aos_task_getspecific() 获取指定任务私有数据区域的内容

使用

添加该组件

任务管理是AliOS Things 默认添加的组件,开发者无需再手动添加。

包含头文件

#include <aos/kernel.h>

使用示例

示例说明:创建一个任务,在任务内创建任务私有数据区域,设置私有区域内容、获取私有区域内容,删除私有数据区域,最后任务退出。

/* 创建任务test_task,任务栈大小为1024字节 */ 
aos_task_new("test_task", test_task, NULL, 1024);

static void test_task(void *paras)
{
    int ret = -1;
    int var = 0;
    aos_task_key_t task_key;
    void *task_value = NULL;

     /* 创建任务私有数据区域*/
    ret = aos_task_key_create(&task_key);
    /* 打印任务名和任务私有数据区域索引值*/
    printf("%s task key %d: \r\n", aos_task_name(), task_key);

    var = 0x5a5a;
     /* 设置当前任务私有数据区域的某索引空闲块内容 */
    ret = aos_task_setspecific(task_key, &var);

    /* 获取当前任务私有数据区域的某索引数据块内容 */
    task_value = aos_task_getspecific(task_key);
    printf("%s task key 0x%x: \r\n", aos_task_name(), *(int*)task_value);

    /* 删除任务私有数据区域的空闲块索引 */
    aos_task_key_delete(task_key);

    /* 任务退出 */
    aos_task_exit(0);
}

API 详情

任务管理的应用层API说明请参考include/aos/kernel.h

aos_task_new()

动态创建一个任务,任务句柄不返回,创建完后自动运行。采用默认优先级AOS_DEFAULT_APP_PRI(32)。受宏RHINO_CONFIG_KOBJ_DYN_ALLOC开关控制。

函数原型

 int aos_task_new(const char *name, void (*fn)(void *), void *arg, int stack_size);

输入参数

name 任务名 '"test_task"'
fn 任务处理函数
arg 任务处理函数的参数
stack_size 任务栈大小(单位:字节)

返回参数

0表示成功,其他值表示失败。具体的返回值见本文档返回参数定义小节。

调用示例

static void test_task(void *paras)
{
    ……
}

aos_task_new("test_task", test_task, NULL, 1024);

aos_task_new_ext()

动态创建一个任务,传入任务句柄,并指定优先级,创建完后自动运行。

函数原型

 int aos_task_new_ext(aos_task_t *task, const char *name, void (*fn)(void *), void *arg, int stack_size, int prio);

输入参数

task 任务句柄
name 任务名 '"test_task"'
fn 任务处理函数
arg 任务处理函数的参数
stack_size 任务栈大小(单位:字节)
prio 任务运行优先级(范围:0~ RHINO_CONFIG_PRI_MAX-2; RHINO_CONFIG_PRI_MAX-1为idle任务优先级) 10

返回参数

0表示成功,其他值表示失败。具体的返回值见本文档返回参数定义小节。

调用示例

static void test_task(void *paras)
{
    ……
}

aos_task_t task_handle;
aos_task_new_ext(&task_handle, "test_task", test_task, NULL, 1024, 10);

aos_task_exit()

任务自动退出。

函数原型

 void aos_task_exit(int code);

输入参数

code 任务退出码,暂时无用

返回参数

调用示例

/* 任务处理函数 */
void task_entry(void *arg)
{
    ……
    aos_task_exit(0);  /* 任务自动退出 */
}

aos_task_delete()

删除任务。

函数原型

 int aos_task_delete(char *name);

输入参数

name 待删除的任务名 '"test_task"'

返回参数

0表示成功,其他值表示失败。具体的返回值见本文档返回参数定义小节。

调用示例

static void test_task(void *paras)
{
    ……
}

aos_task_new("test_task", test_task, NULL, 1024);
……
aos_task_delete("test_task");

aos_task_name()

获得当前任务名字。

函数原型

 const char *aos_task_name(void);

输入参数

返回参数

任务名字符串。

调用示例

char *task_name;
task_name = aos_task_name();
printf("task name: %s\r\n", task_name);

aos_task_key_create()

申请一个任务私有数据区域。

函数原型

 int aos_task_key_create(aos_task_key_t *key);

输入参数

key 任务私有数据区域的索引,新分配的索引保存在该参数中

返回参数

0表示成功,失败返回-EINVAL。

调用示例

int ret = -1;
aos_task_key_t task_key;

ret = aos_task_key_create(&task_key);

aos_task_key_delete()

释放一个任务私有数据区域。

函数原型

void aos_task_key_delete(aos_task_key_t key);

输入参数

key 任务私有数据区域的索引,删除该索引指向的任务私有数据区域

返回参数

调用示例

int ret = -1;
aos_task_key_t task_key;
ret = aos_task_key_create(&task_key);
……
aos_task_key_delete(task_key);

aos_task_setspecific()

设置指定任务私有数据区域的内容。

函数原型

int aos_task_setspecific(aos_task_key_t key, void *vp);

输入参数

key 任务私有数据区域的索引,设置该索引指向的任务私有数据区域
vp 设置到任务私有数据区域的值

返回参数

0表示成功,其他值表示失败。具体的返回值见本文档返回参数定义小节。

调用示例

int ret = -1;
int var = 0;
aos_task_key_t task_key;

ret = aos_task_key_create(&task_key);
var = 0x5a5a;
ret = aos_task_setspecific(task_key, &var);

aos_task_getspecific()

获取指定任务私有数据区域的内容。

函数原型

void *aos_task_getspecific(aos_task_key_t key);

输入参数

key 任务私有数据区域的索引,获取该索引指向的任务私有数据区域的内容

返回参数

指定任务私有数据区域的内容。

调用示例

int ret = -1;
int var = 0;
aos_task_key_t task_key;
void *task_value = NULL;

ret = aos_task_key_create(&task_key);
var = 0x5a5a;
ret = aos_task_setspecific(task_key, &var);
……
task_value = aos_task_getspecific(task_key);

其他

返回参数定义

返回值定义在core/rhino/include/k_err.h文件中。该文件为内部文件,出错时可根据返回值查阅该文件确认出错原因。

typedef enum
{
    RHINO_SUCCESS = 0u,
    RHINO_SYS_FATAL_ERR,
    RHINO_SYS_SP_ERR,
    RHINO_RUNNING,
    RHINO_STOPPED,
    RHINO_INV_PARAM,
    RHINO_NULL_PTR,
    RHINO_INV_ALIGN,
    RHINO_KOBJ_TYPE_ERR,
    RHINO_KOBJ_DEL_ERR,
    RHINO_KOBJ_DOCKER_EXIST,
    RHINO_KOBJ_BLK,
    RHINO_KOBJ_SET_FULL,
    RHINO_NOTIFY_FUNC_EXIST,
  
    RHINO_MM_POOL_SIZE_ERR = 100u,
    RHINO_MM_ALLOC_SIZE_ERR,
    RHINO_MM_FREE_ADDR_ERR,
    RHINO_MM_CORRUPT_ERR,
    RHINO_DYN_MEM_PROC_ERR,
    RHINO_NO_MEM,
    RHINO_RINGBUF_FULL,
    RHINO_RINGBUF_EMPTY,

    RHINO_SCHED_DISABLE = 200u,
    RHINO_SCHED_ALREADY_ENABLED,
    RHINO_SCHED_LOCK_COUNT_OVF,
    RHINO_INV_SCHED_WAY,

    RHINO_TASK_INV_STACK_SIZE = 300u,
    RHINO_TASK_NOT_SUSPENDED,
    RHINO_TASK_DEL_NOT_ALLOWED,
    RHINO_TASK_SUSPEND_NOT_ALLOWED,
    RHINO_TASK_CANCELED,
    RHINO_SUSPENDED_COUNT_OVF,
    RHINO_BEYOND_MAX_PRI,
    RHINO_PRI_CHG_NOT_ALLOWED,
    RHINO_INV_TASK_STATE,
    RHINO_IDLE_TASK_EXIST,

    RHINO_NO_PEND_WAIT = 400u,
    RHINO_BLK_ABORT,
    RHINO_BLK_TIMEOUT,
    RHINO_BLK_DEL,
    RHINO_BLK_INV_STATE,
    RHINO_BLK_POOL_SIZE_ERR,
  
    RHINO_TIMER_STATE_INV = 500u,

    RHINO_NO_THIS_EVENT_OPT = 600u,

    RHINO_BUF_QUEUE_INV_SIZE = 700u,
    RHINO_BUF_QUEUE_SIZE_ZERO,
    RHINO_BUF_QUEUE_FULL,
    RHINO_BUF_QUEUE_MSG_SIZE_OVERFLOW,
    RHINO_QUEUE_FULL,
    RHINO_QUEUE_NOT_FULL,

    RHINO_SEM_OVF = 800u,
    RHINO_SEM_TASK_WAITING,

    RHINO_MUTEX_NOT_RELEASED_BY_OWNER = 900u,
    RHINO_MUTEX_OWNER_NESTED,
    RHINO_MUTEX_NESTED_OVF,

    RHINO_NOT_CALLED_BY_INTRPT = 1000u,
    RHINO_TRY_AGAIN,
  
    RHINO_WORKQUEUE_EXIST = 1100u,
    RHINO_WORKQUEUE_NOT_EXIST,
    RHINO_WORKQUEUE_WORK_EXIST,
    RHINO_WORKQUEUE_BUSY,
    RHINO_WORKQUEUE_WORK_RUNNING,

    RHINO_TASK_STACK_OVF = 1200u,
    RHINO_INTRPT_STACK_OVF,

    RHINO_STATE_ALIGN = INT_MAX /* keep enum 4 bytes at 32bit machine */
} kstat_t;