UCOSIII信号量和互斥信号量

Posted 想成为大师啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UCOSIII信号量和互斥信号量相关的知识,希望对你有一定的参考价值。

1、UCOSIII信号量

1.1、信号量简介:

信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被锁部分代码的钥匙被再次释放才能继续执行。

信号量用来控制对共享资源的保护,但是现在基本用来做任务同步用

要想获取资源的任务必须执行 “等待” 操作,如果该资源对应的信号量有效值大于1,则任务可以获得该资源,任务继续运行。如果该信号量的有效值为0,则任务加入等待信号量的任务表中。如果等待时间超过某一个设定值,该信号量仍然没有被释放掉,则等待信号量的任务就进入就绪态,如果将等待时间设置为0的话任务就将一直等待该信号量

信号量通常分为两种:二进制信号量和计数型信号量

  • 二进制信号量只能取0和1两个值,计数型信号量的信号量值大于1,计数型信号量的范围由 0S_SEM_STR决定,OS_SEM_CTR可以为8位,16位和32位,取值范围分别为:0~255、0~65535和0~4294967295
  • 二值信号量用于那些一次只能一个任务使用的资源,比如 I/O 设备,打印机计,数型信号量用于某些资源可以同时被几个任务所使用,比如一个缓存池有10个缓存块,那么同时最多可以支持10个任务来使用内存池。

1.2、信号量API函数:

函数名作用
OSSemCreate()建立一个信号量
OSSemDel()删除一个信号量
OSSemPend()等待一个信号量
OSSemPendAbrot()取消等待
OSSemPost()释放或者发出一个信号量
OSSemSet()强制设置一个信号量的值

OSSemCreate 创建信号量:

void  OSSemCreate (OS_SEM      *p_sem,
                   CPU_CHAR    *p_name,
                   OS_SEM_CTR   cnt,
                   OS_ERR      *p_err)
  • OS_SEM 信号量:

    typedef  struct  os_sem              OS_SEM;
    
  • CPU_CHAR 信号量命名:

    typedef            char        CPU_CHAR;                        /*  8-bit character                                     */
    
  • OS_SEM_CTR 信号量初始值:

    typedef   CPU_INT32U      OS_SEM_CTR;                  /* Semaphore value                                     16/<32> */
    
  • OS_ERR 信号量返回错误信息:

    typedef  enum  os_err 
        OS_ERR_NONE                      =     0u,
    
        OS_ERR_A                         = 10000u,
        OS_ERR_ACCEPT_ISR                = 10001u,
    
        OS_ERR_B                         = 11000u,
    
        OS_ERR_C                         = 12000u,
        OS_ERR_CREATE_ISR                = 12001u,
    
        OS_ERR_D                         = 13000u,
        OS_ERR_DEL_ISR                   = 13001u,
    
        OS_ERR_E                         = 14000u,
    
        OS_ERR_F                         = 15000u,
        OS_ERR_FATAL_RETURN              = 15001u,
    
        OS_ERR_FLAG_GRP_DEPLETED         = 15101u,
        OS_ERR_FLAG_NOT_RDY              = 15102u,
        OS_ERR_FLAG_PEND_OPT             = 15103u,
        OS_ERR_FLUSH_ISR                 = 15104u,
    
        OS_ERR_G                         = 16000u,
    
        OS_ERR_H                         = 17000u,
    
        OS_ERR_I                         = 18000u,
        OS_ERR_ILLEGAL_CREATE_RUN_TIME   = 18001u,
        OS_ERR_INT_Q                     = 18002u,
        OS_ERR_INT_Q_FULL                = 18003u,
        OS_ERR_INT_Q_SIZE                = 18004u,
        OS_ERR_INT_Q_STK_INVALID         = 18005u,
        OS_ERR_INT_Q_STK_SIZE_INVALID    = 18006u,
    
        OS_ERR_J                         = 19000u,
    
        OS_ERR_K                         = 20000u,
    
        OS_ERR_L                         = 21000u,
        OS_ERR_LOCK_NESTING_OVF          = 21001u,
    
        OS_ERR_M                         = 22000u,
    
        OS_ERR_MEM_CREATE_ISR            = 22201u,
        OS_ERR_MEM_FULL                  = 22202u,
        OS_ERR_MEM_INVALID_P_ADDR        = 22203u,
        OS_ERR_MEM_INVALID_BLKS          = 22204u,
        OS_ERR_MEM_INVALID_PART          = 22205u,
        OS_ERR_MEM_INVALID_P_BLK         = 22206u,
        OS_ERR_MEM_INVALID_P_MEM         = 22207u,
        OS_ERR_MEM_INVALID_P_DATA        = 22208u,
        OS_ERR_MEM_INVALID_SIZE          = 22209u,
        OS_ERR_MEM_NO_FREE_BLKS          = 22210u,
    
        OS_ERR_MSG_POOL_EMPTY            = 22301u,
        OS_ERR_MSG_POOL_NULL_PTR         = 22302u,
    
        OS_ERR_MUTEX_NOT_OWNER           = 22401u,
        OS_ERR_MUTEX_OWNER               = 22402u,
        OS_ERR_MUTEX_NESTING             = 22403u,
    
        OS_ERR_N                         = 23000u,
        OS_ERR_NAME                      = 23001u,
        OS_ERR_NO_MORE_ID_AVAIL          = 23002u,
    
        OS_ERR_O                         = 24000u,
        OS_ERR_OBJ_CREATED               = 24001u,
        OS_ERR_OBJ_DEL                   = 24002u,
        OS_ERR_OBJ_PTR_NULL              = 24003u,
        OS_ERR_OBJ_TYPE                  = 24004u,
    
        OS_ERR_OPT_INVALID               = 24101u,
    
        OS_ERR_OS_NOT_RUNNING            = 24201u,
        OS_ERR_OS_RUNNING                = 24202u,
    
        OS_ERR_P                         = 25000u,
        OS_ERR_PEND_ABORT                = 25001u,
        OS_ERR_PEND_ABORT_ISR            = 25002u,
        OS_ERR_PEND_ABORT_NONE           = 25003u,
        OS_ERR_PEND_ABORT_SELF           = 25004u,
        OS_ERR_PEND_DEL                  = 25005u,
        OS_ERR_PEND_ISR                  = 25006u,
        OS_ERR_PEND_LOCKED               = 25007u,
        OS_ERR_PEND_WOULD_BLOCK          = 25008u,
    
        OS_ERR_POST_NULL_PTR             = 25101u,
        OS_ERR_POST_ISR                  = 25102u,
    
        OS_ERR_PRIO_EXIST                = 25201u,
        OS_ERR_PRIO                      = 25202u,
        OS_ERR_PRIO_INVALID              = 25203u,
    
        OS_ERR_PTR_INVALID               = 25301u,
    
        OS_ERR_Q                         = 26000u,
        OS_ERR_Q_FULL                    = 26001u,
        OS_ERR_Q_EMPTY                   = 26002u,
        OS_ERR_Q_MAX                     = 26003u,
        OS_ERR_Q_SIZE                    = 26004u,
    
        OS_ERR_R                         = 27000u,
        OS_ERR_REG_ID_INVALID            = 27001u,
        OS_ERR_ROUND_ROBIN_1             = 27002u,
        OS_ERR_ROUND_ROBIN_DISABLED      = 27003u,
    
        OS_ERR_S                         = 28000u,
        OS_ERR_SCHED_INVALID_TIME_SLICE  = 28001u,
        OS_ERR_SCHED_LOCK_ISR            = 28002u,
        OS_ERR_SCHED_LOCKED              = 28003u,
        OS_ERR_SCHED_NOT_LOCKED          = 28004u,
        OS_ERR_SCHED_UNLOCK_ISR          = 28005u,
    
        OS_ERR_SEM_OVF                   = 28101u,
        OS_ERR_SET_ISR                   = 28102u,
    
        OS_ERR_STAT_RESET_ISR            = 28201u,
        OS_ERR_STAT_PRIO_INVALID         = 28202u,
        OS_ERR_STAT_STK_INVALID          = 28203u,
        OS_ERR_STAT_STK_SIZE_INVALID     = 28204u,
        OS_ERR_STATE_INVALID             = 28205u,
        OS_ERR_STATUS_INVALID            = 28206u,
        OS_ERR_STK_INVALID               = 28207u,
        OS_ERR_STK_SIZE_INVALID          = 28208u,
        OS_ERR_STK_LIMIT_INVALID         = 28209u,
    
        OS_ERR_T                         = 29000u,
        OS_ERR_TASK_CHANGE_PRIO_ISR      = 29001u,
        OS_ERR_TASK_CREATE_ISR           = 29002u,
        OS_ERR_TASK_DEL                  = 29003u,
        OS_ERR_TASK_DEL_IDLE             = 29004u,
        OS_ERR_TASK_DEL_INVALID          = 29005u,
        OS_ERR_TASK_DEL_ISR              = 29006u,
        OS_ERR_TASK_INVALID              = 29007u,
        OS_ERR_TASK_NO_MORE_TCB          = 29008u,
        OS_ERR_TASK_NOT_DLY              = 29009u,
        OS_ERR_TASK_NOT_EXIST            = 29010u,
        OS_ERR_TASK_NOT_SUSPENDED        = 29011u,
        OS_ERR_TASK_OPT                  = 29012u,
        OS_ERR_TASK_RESUME_ISR           = 29013u,
        OS_ERR_TASK_RESUME_PRIO          = 29014u,
        OS_ERR_TASK_RESUME_SELF          = 29015u,
        OS_ERR_TASK_RUNNING              = 29016u,
        OS_ERR_TASK_STK_CHK_ISR          = 29017u,
        OS_ERR_TASK_SUSPENDED            = 29018u,
        OS_ERR_TASK_SUSPEND_IDLE         = 29019u,
        OS_ERR_TASK_SUSPEND_INT_HANDLER  = 29020u,
        OS_ERR_TASK_SUSPEND_ISR          = 29021u,
        OS_ERR_TASK_SUSPEND_PRIO         = 29022u,
        OS_ERR_TASK_WAITING              = 29023u,
    
        OS_ERR_TCB_INVALID               = 29101u,
    
        OS_ERR_TLS_ID_INVALID            = 29120u,
        OS_ERR_TLS_ISR                   = 29121u,
        OS_ERR_TLS_NO_MORE_AVAIL         = 29122u,
        OS_ERR_TLS_NOT_EN                = 29123u,
        OS_ERR_TLS_DESTRUCT_ASSIGNED     = 29124u,
    
        OS_ERR_TICK_PRIO_INVALID         = 29201u,
        OS_ERR_TICK_STK_INVALID          = 29202u,
        OS_ERR_TICK_STK_SIZE_INVALID     = 29203u,
        OS_ERR_TICK_WHEEL_SIZE           = 29204u,
    
        OS_ERR_TIME_DLY_ISR              = 29301u,
        OS_ERR_TIME_DLY_RESUME_ISR       = 29302u,
        OS_ERR_TIME_GET_ISR              = 29303u,
        OS_ERR_TIME_INVALID_HOURS        = 29304u,
        OS_ERR_TIME_INVALID_MINUTES      = 29305u,
        OS_ERR_TIME_INVALID_SECONDS      = 29306u,
        OS_ERR_TIME_INVALID_MILLISECONDS = 29307u,
        OS_ERR_TIME_NOT_DLY              = 29308u,
        OS_ERR_TIME_SET_ISR              = 29309u,
        OS_ERR_TIME_ZERO_DLY             = 29310u,
    
        OS_ERR_TIMEOUT                   = 29401u,
    
        OS_ERR_TMR_INACTIVE              = 29501u,
        OS_ERR_TMR_INVALID_DEST          = 29502u,
        OS_ERR_TMR_INVALID_DLY           = 29503u,
        OS_ERR_TMR_INVALID_PERIOD        = 29504u,
        OS_ERR_TMR_INVALID_STATE         = 29505u,
        OS_ERR_TMR_INVALID               = 29506u,
        OS_ERR_TMR_ISR                   = 29507u,
        OS_ERR_TMR_NO_CALLBACK           = 29508u,
        OS_ERR_TMR_NON_AVAIL             = 29509u,
        OS_ERR_TMR_PRIO_INVALID          = 29510u,
        OS_ERR_TMR_STK_INVALID           = 29511u,
        OS_ERR_TMR_STK_SIZE_INVALID      = 29512u,
        OS_ERR_TMR_STOPPED               = 29513u,
    
        OS_ERR_U                         = 30000u,
    
        OS_ERR_V                         = 31000u,
    
        OS_ERR_W                         = 32000u,
    
        OS_ERR_X                         = 33000u,
    
        OS_ERR_Y                         = 34000u,
        OS_ERR_YIELD_ISR                 = 34001u,
    
        OS_ERR_Z                         = 35000u
     OS_ERR;
    

OSSemPend 请求信号量:

OS_SEM_CTR  OSSemPend (OS_SEM   *p_sem,
                       OS_TICK   timeout,
                       OS_OPT    opt,
                       CPU_TS   *p_ts,
                       OS_ERR   *p_err)

2、UCOSIII互斥信号量

2.1、优先级反转:

优先级反转在可剥夺反转内核中是非常常见的,在实时系统中不允许出现这种现象,这样会破坏任务的预期顺序,可能会导致严重的后果

任务优先级:任务H > 任务M > 任务L

时间线从左往右

2.2、互斥信号量:

为了避免优先级反转这个问题,UCOSIII支持一种特殊的二进制信号量:互斥信号量,用它可以解决优先级反转问题。

2.2、互斥信号量API函数:

函数名作用
OSMutexCreate()建立一个互斥信号量
OSMutexDel()删除一个互斥信号量
OSMutexPend()等待一个互斥信号量
OSMutexPendAbrot()取消等待
OSMutexPost()释放或者发布一个互斥信号量

3、UCOSIII任务内嵌信号量

在UCOSIII中每个任务都有自己的内嵌的信号量,这种功能不仅能够简化代码,而且比使用独立的信号量更有效。任务信号量是直接内嵌在UCOSIII中的,任务信号量相关代码在 os_task.c 中

函数名作用
OSTaskSemPend()等待一个任务信号量
OSTaskSemPendAbrot()取消等待任务信号量
OSTaskSemPost()发布任务信号量
OSTaskSemSet()强行设置任务信号量计数

以上是关于UCOSIII信号量和互斥信号量的主要内容,如果未能解决你的问题,请参考以下文章

操作系统

UCOSIII中的节拍列表更新

信号量互斥量同步变量条件变量和事件变量

进程互斥锁--二值信号量

理解互斥量和信号量

信号量与互斥锁的区别