本文主要是介绍ucos信号量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
信号量SEMAPHORES
官方释义
信号量最初是一种机械的信号机制。铁路工业利用这种装置为多列火车共用的铁路轨道提供了一种互斥形式。在这种形式下,信号量通过关闭一组机械臂来锁定当前使用的铁轨上的火车来向火车发出信号。当轨道可用时,手臂就会向上摆动,等待的火车就会继续前进。在软件中使用信号量作为相互排斥的手段的概念是由荷兰计算机科学家Edgser Dijkstra在1959年发明的。在计算机软件中,信号量是大多数多任务内核提供的一种协议机制。信号量,最初用于控制对共享资源的访问,但现在它们被用于同步。信号量最初是一种“锁机制”,代码获得该锁的密钥以继续执行。获取密钥意味着正在执行的任务有权限进入其他锁定代码的部分。输入一段锁定代码会导致任务等待,直到密钥可用。
通常,存在两种类型的信号量:二进制信号量和计数信号量。顾名思义,二进制信号量只能取两个值:0或1。计数信号量允许0到255、65,535或4,294,967,295之间的值,这取决于信号量机制分别是使用8位、16位或32位实现的。对于HC/OS-III,信号量的最大值由数据类型Os_SEM CTR(见os_type.h)决定,可以根据需要进行修改。除了信号量的值,还会跟踪等待信号量可用性的任务。
说白了,信号量可以用于资源重用检测,同时也可以用来传递一些简单信号。
信号量的结构为
struct os_sem { /* Semaphore *//* ------------------ GENERIC MEMBERS ------------------ */OS_OBJ_TYPE Type; /* Should be set to OS_OBJ_TYPE_SEM */CPU_CHAR *NamePtr; /* Pointer to Semaphore Name (NUL terminated ASCII) */OS_PEND_LIST PendList; /* List of tasks waiting on semaphore */
#if OS_CFG_DBG_EN > 0uOS_SEM *DbgPrevPtr;OS_SEM *DbgNextPtr;CPU_CHAR *DbgNamePtr;
#endif/* ------------------ SPECIFIC MEMBERS ------------------ */OS_SEM_CTR Ctr;CPU_TS TS;
};
其中最常用的是OS_SEM_CTR Ctr;
,在创建信号量时,要设置信号量的初始值。
关于信号量的系统函数如下
- void OSSemCreate (OS_SEM *p_sem,CPU_CHAR *p_name,OS_SEM_CTR cnt,OS_ERR *p_err)
- p_sem:信号量本体;
- p_name:信号量的名称;
- cnt:信号量的初始值;
- p_err:用于传递错误信息的指针。
- OS_SEM_CTR OSSemPost (OS_SEM *p_sem,OS_OPT opt,OS_ERR *p_err)
作用是增加信号量cnt的值 - OS_SEM_CTR OSSemPend (OS_SEM *p_sem,OS_TICK timeout,OS_OPT opt,CPU_TS *p_ts,OS_ERR *p_err)
- timeout: 允许任务在timeout时间结束后还没有收到信号量的情况下直接执行代码,当timeout=0时则无限等待;
- opt:用于设置当信号量未到达时是否阻塞;当opt=OS_OPT_PEND_BLOCKING时,在未获取信号量或者超时时阻塞程序。当opt=OS_OPT_PEN_NON_BLOCKING时,OSSemPend()将返回错误代码并执行后面的代码。
- p_ts:用于记录当接受到信号量/信号量删除/信号量超时时刻的时间戳。
函数的作用是等待并接受信号量,并自减信号量值cnt,当信号量值为0时,该函数阻塞(设置了OS_OPT_PEND_BLOCKING时)
还有几个不常用的函数OSSemDel,OSSemSet,OSSemPendAbort
示例
-
在初始任务中创建信号量
OSSemCreate ((OS_SEM* )&MY_SEM,(CPU_CHAR* )"MY_SEM",(OS_SEM_CTR)0, (OS_ERR* )&err);
-
在LED0任务中释放信号量(设定为每3秒释放一次信号量)
void led0_task(void *p_arg){OS_ERR err;p_arg = p_arg;while(1){OSSemPost(&MY_SEM,OS_OPT_POST_1,&err);OSTimeDlyHMSM(0,0,3,0,OS_OPT_TIME_HMSM_STRICT,&err); }}
-
在LED1任务中接受信号量(设定为接受到信号量后闪烁灯泡一次)
void led1_task(void *p_arg){CPU_TS ts;OS_ERR err;p_arg = p_arg;while(1){OSSemPend(&MY_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); LED0=0;OSTimeDlyHMSM(0,0,0,50,OS_OPT_TIME_HMSM_STRICT,&err); LED0=1;OSTimeDlyHMSM(0,0,0,50,OS_OPT_TIME_HMSM_STRICT,&err); }}
运行效果是每3秒灯泡快闪一次。
这篇关于ucos信号量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!