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 > 0u
    OS_SEM              *DbgPrevPtr;
    OS_SEM              *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
#endif
                                                            /* ------------------ SPECIFIC MEMBERS ------------------ */
    OS_SEM_CTR           Ctr;
    CPU_TS               TS;
};

其中最常用的是OS_SEM_CTR Ctr;,在创建信号量时,要设置信号量的初始值。

关于信号量的系统函数如下

  1. 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:用于传递错误信息的指针。
  2. OS_SEM_CTR OSSemPost (OS_SEM *p_sem,OS_OPT opt,OS_ERR *p_err)
    作用是增加信号量cnt的值
  3. 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

示例

  1. 在初始任务中创建信号量

    OSSemCreate ((OS_SEM*	)&MY_SEM,
                (CPU_CHAR*	)"MY_SEM",
                (OS_SEM_CTR)0,		
                (OS_ERR*	)&err);	
    
  2. 在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); 
         }
     }
    
  3. 在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秒灯泡快闪一次。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值