当前位置: 首页 > 工具软件 > AliOS Things > 使用案例 >

alios thing 信号量_信号量_AliOS Things内核_API参考文档_AliOS Things 文档_IoT物联网操作系统 - 阿里云...

秦胡媚
2023-12-01

对于多任务,甚至多核的操作系统,需要访问共同的系统资源。共享资源包括软件资源和硬件资源,软件共享资源主要是共享内存,包括共享变量、共享队列等等,硬件共享资源包括一些硬件设备的访问,例如:输入/输出设备。为了避免多个任务访问共享资源时相互影响甚至冲突,需要对共享资源进行保护,有下列几种处理方式:开关中断、信号量(semphore)、互斥量(mutex)。

开关中断:一般用于单核平台多任务之间的互斥,通过关闭任务的调度,从而达到单任务访问共享资源的目的。缺点是会影响中断响应时间。

信号量:多任务可以通过获取信号量来获取访问共享资源,可以配置信号量的数目,让多个任务同时获取信号量,当信号量无法获取时,相关任务会按照优先级排序等待信号量释放,并让出CPU资源;缺点是存在高低任务优先级反转的问题。

互斥量:任务也是通过获取mutex来获取访问共享资源的门禁,但是单次只有一个任务能获取到该互斥量。互斥量通过动态调整任务的优先级来解决高低优先级反转的问题。

本章节介绍AliOS Thngs上的信号量接口。

API 列表

aos_sem_new()

创建信号量对象

aos_sem_free()

删除信号量对象

aos_sem_wait()

请求一个信号量

aos_sem_signal()

释放一个信号量

aos_sem_is_valid()

判断信号量对象是否有效

aos_sem_signal_all()

释放信号量,并唤醒所有阻塞在该信号量上的任务

使用

添加该组件

信号量是AliOS Things 默认添加的组件,开发者无需再手动添加。

包含头文件

#include

使用示例

示例说明:当前任务创建一个信号量和子任务,并等待子任务释放信号量。

static aos_sem_t g_sem_taskexit_sync;

unsigned int stack_size = 1024;

int ret = -1;

....

static void task1(void *arg)

{

....

/*释放信号量*/

aos_sem_signal(&g_sem_taskexit_sync);

....

}

/*当前任务:创建信号量,信号量初始count为0*/

ret = aos_sem_new(&g_sem_taskexit_sync, 0);

if (ret != 0) {

printf("sem create failed\r\n");

...

}

....

/*判断信号量是否可用*/

ret = aos_sem_is_valid(&g_sem_taskexit_sync);

if (ret == 0) {

printf("sem is invalid\r\n");

...

}

/*创建新任务task1*/

ret = aos_task_new("task1", task1, NULL, stack_size);

if (ret != 0) {

printf("timer create failed\r\n");

...

}

....

/*获取信号量,由于初始值为0,这里获取不到信号量,当前任务进入睡眠并发生切换。

参数 AOS_WAIT_FOREVER 表示永久等待,知道获得信号量 */

aos_sem_wait(&g_sem_taskexit_sync, AOS_WAIT_FOREVER);

/*获取到信号量,当前任务继续执行下去*/

printf("task1 exit!\r\n");

....

/*删除信号量*/

aos_sem_free(&g_sem_taskexit_sync);

API 详情

aos_sem_new()

创建信号量对象。

函数原型

int aos_sem_new(aos_sem_t *sem, int count);

输入参数

sem

信号量句柄,需要用户定义一个aos_sem_t结构体变量

count

信号量初始个数

1

返回参数

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

调用示例

aos_sem_t sem_handle;

int status;

status = aos_sem_new(&sem_handle, 1);

aos_sem_free()

删除信号量对象。

函数原型

void aos_sem_free(aos_sem_t *sem);

输入参数

sem

信号量句柄

返回参数

调用示例

aos_sem_t sem_handle;

int status;

status = aos_sem_new(&sem_handle, 1);

……

aos_sem_free(&sem_handle);

aos_sem_signal()

释放一个信号量。

函数原型

void aos_sem_signal(aos_sem_t *sem);

输入参数

sem

信号量句柄

返回参数

调用示例

aos_sem_t sem_handle;

int status;

status = aos_sem_new(&sem_handle, 1);

……

aos_sem_signal(&sem_handle);

aos_sem_signal_all()

释放信号量,并唤醒所有阻塞在该信号量上的任务。

函数原型

void aos_sem_signal_all(aos_sem_t *sem);

输入参数

sem

信号量句柄

返回参数

调用示例

aos_sem_t sem_handle;

int status;

status = aos_sem_new(&sem_handle, 1);

……

aos_sem_signal_all(&sem_handle);

aos_sem_wait()

请求一个信号量,若获取不到且超时时间不为0,则任务将被阻塞。

函数原型

int aos_sem_wait(aos_sem_t *sem, unsigned int timeout);

输入参数

sem

信号量句柄

timeout

等待超时时间。0表示不超时,立即返回;AOS_WAIT_FOREVER表示永久等待;其他数值表示超时时间,单位ms

返回参数

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

调用示例

aos_sem_t sem_handle;

int status;

status = aos_sem_new(&sem_handle, 1);

……

status = aos_sem_wait(&sem_handle, AOS_WAIT_FOREVER);

aos_sem_is_valid()

判断信号量对象是否有效。

函数原型

int aos_sem_is_valid(aos_sem_t *sem);

输入参数

sem

信号量句柄

返回参数

1表示有效,0表示无效。

调用示例

extern aos_sem_t sem_handle;

int status;

/* 信号量句柄在别的文件定义,因此在使用前先判断一下是否有效 */

status = aos_sem_is_valid(&sem_handle);

if (status == 0) {

printf("sem is invalid\r\n");

...

}

其他

返回参数定义

返回值定义在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;

使用注意事项

1)在中断中禁止信号量获取检测 中断服务程序的执行不能被阻塞,因此不能在中断中调用请求信号量的接口。有些内核将这种判断处理交由上层软件进行判断和使用,AliOS Things的内核会在请求信号量时进行检测,如果是中断上下文,则直接返回失败。在中断上下文可以释放信号量。

2) 请求信号量时的非等待、永远等待、延时的区别 上层应用在获取信号量时,需要按照实际的需求来安排信号量获取策略。aos_sem_wait传入延时为0时,当获取不到信号量会立即返回并报失败;超时时间为AOS_WAIT_FOREVER时,会永久等待,直到获取到信号量,可能会造成该任务无法继续运行;其他值表示最大延迟的时间上限,达到上限时,即使未获取到信号量,任务也会被唤醒,并返回状态为超时。

3) 信号量优先级反转问题 优先级反转问题出现在高、低两个优先级任务同时使用信号量访问互斥资源时。当高优先级任务请求的信号量被低优先级任务已经占用时,高优先级任务会被阻塞。此时如果有一个中优先级任务,那么中优先级任务能抢占低优先级任务而得到CPU资源。这个时候出现了一种情况,由于资源被低优先级任务占用但由于低优先级任务得不到CPU资源而没有机会运行,最终导致高优先级任务得不到调度。

互斥信号量支持解决优先级反转问题,其方法是动态提高占用信号量的任务的运行优先级。

 类似资料: