赞
踩
1.1 信号量
信号量(Semaphore) 是一种实现任务间通信的机制,实现任务之间同步或临界资源的互斥访问。在多任务操作系统中,不同的任务之间需要同步运行,信号量功能可以为用户提供这方面的支持。
1.2 信号量的使用方式
信号量可以被任务获取或者申请,不同的信号量通过信号量索引号来唯一确定,每个信号量都有一个计数值和任务队列。
通常一个信号量的计数值用于对应有效的资源数,表示剩下的可被占用的互斥资源数,其值的含义分两种情况:
0: 表示没有积累下来的 Post 操作,且有可能有在此信号量上阻塞的任务;
正值: 表示有一个或多个 Post 下来的释放操作;
当任务申请(Pend)信号量时,如果申请成功,则信号量的计数值递减,如若申请失败,则挂起在该信号量的等待任务队列上,一旦有任务释放该信号量,则等待任务队列中的任务被唤醒开始执行。
1.3 信号量的使用场景
信号量是一种非常灵活的同步方式,可以运用在多种场合中,实现锁、同步、资源计数等功能,也能方便的用于任务与任务,中断与任务的同步中。
互斥锁
用作互斥时,信号量创建后记数是满的,在需要使用临界资源时,先申请信号量,使其变空,这样其他任务需要使用临界资源时就会因为无法申请到信号量而阻塞,从而保证了临界资源的安全。
任务间同步
用作同步时,信号量在创建后被置为空,任务1申请信号量而阻塞,任务2在某种条件发生后,释放信号量,于是任务1得以进入 READY 或 RUNNING 态,从而达到了两个任务间的同步。
资源计数
用作资源计数时,信号量的作用是一个特殊的计数器,可以递增或者递减,但是值永远不能为负值,典型的应用场景是生产者与消费者的场景。
中断与任务的同步
用作中断与任务的同步时,可以在中断未触发时将信号量的值置为0,从而堵塞断服务处理任务,一旦中断被触发,则唤醒堵塞的中断服务处理任务进行中断处理。
以下任务管理接口位于 kernel/liteos_m/components/cmsis/2.0/cmsis_os2.h。
业务BUILD.gn中包含路径
include_dirs = [
“//utils/native/lite/include”,
“//kernel/liteos_m/components/cmsis/2.0”,
]
| API | 说明 |
|---|---|
| osSemaphoreNew | 创建并初始化一个信号量 |
| osSemaphoreGetName | 获取一个信号量的名字 |
| osSemaphoreAcquire | 获取一个信号量的令牌,若获取不到,则会超时返回 |
| osSemaphoreRelease | 释放一个信号量的令牌,但是令牌的数量不超过初始定义的令牌数 |
| osSemaphoreGetCount | 获取当前信号量的令牌数量 |
| osSemaphoreDelete | 删除一个信号量 |
#include <stdio.h> #include <stdlib.h> #include "ohos_init.h" #include "cmsis_os2.h" #define BUFFER_SIZE 5U #define RTOSV2_PRINTF(fmat,...)\ do{\ printf("RTOSV2.0_TEST:");\ printf(fmat,##__VA_ARGS__);\ printf("\r\n");\ }while(0) static int product_number = 0; osSemaphoreId_t empty_id; osSemaphoreId_t filled_id; osThreadId_t newThread(char* name,osThreadFunc_t func,void* arg){ osThreadAttr_t attr = { name,0,NULL,0,NULL,1024*2,osPriorityNormal,0,0 }; osThreadId_t tid = osThreadNew(func,arg,&attr); if(tid == NULL){ RTOSV2_PRINTF("osThreadNew(%s) failed.",name); }else{ RTOSV2_PRINTF("osThreadNew(%s) succees,thread id:%d.",name,tid); } return tid; } void producer_thread(void* arg){ (void) arg; while(1){ osSemaphoreAcquire(empty_id,osWaitForever); product_number++; RTOSV2_PRINTF("%s producers a product,now product number :%d.",osThreadGetName(osThreadGetId()),product_number); osDelay(4); osSemaphoreRelease(filled_id); } } void consumer_thread(void* arg){ (void) arg; while(1){ osSemaphoreAcquire(filled_id,osWaitForever); product_number--; RTOSV2_PRINTF("%s consumer a product,now product number :%d.",osThreadGetName(osThreadGetId()),product_number); osDelay(4); osSemaphoreRelease(empty_id); } } void rtosv2_semp_main(void* arg){ (void) arg; osThreadId_t ctid1 = newThread("consumer1",consumer_thread,NULL); osThreadId_t ctid2 = newThread("consumer2",consumer_thread,NULL); osThreadId_t ctid3 = newThread("producter1",producer_thread,NULL); osThreadId_t ctid4 = newThread("producter2",producer_thread,NULL); osThreadId_t ctid5 = newThread("producter3",producer_thread,NULL); empty_id = osSemaphoreNew(BUFFER_SIZE,BUFFER_SIZE,NULL); filled_id = osSemaphoreNew(BUFFER_SIZE, 0U, NULL); osDelay(50); osThreadTerminate(ctid1); osThreadTerminate(ctid2); osThreadTerminate(ctid3); osThreadTerminate(ctid4); osThreadTerminate(ctid5); osSemaphoreDelete(empty_id); osSemaphoreDelete(filled_id); } void SemaphoreEntry(void){ osThreadAttr_t attr; attr.name = "rtosv2_semp_main"; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = 10240; attr.priority = osPriorityNormal; if (osThreadNew(rtosv2_semp_main, NULL, &attr) == NULL) { printf("[semaphore_demo] Falied to create rtosv2_semp_main!\n"); } } SYS_RUN(SemaphoreEntry);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。