UCOS学习笔记(六)信号量

前言

这是用markdown写的第一篇博客,如果写的不好见谅啦

信号量

基本概念及一些注意事项

将信号量用于同步的概念是荷兰的电脑科学家Edgser Dijkstra 在1959 年发明的。在电脑软件中,信号量是一种用于多任务调度的协议机制。
信号量像是一种上锁机制,代码必须获得相应的钥匙才能继续执行,一旦获得了钥匙就意味着该任务具有了进入被锁部分代码的权限。
信号量用于控制对共享资源的保护,但是现在基本用来做任务同步用
对共享资源保护的方法:关中断、对任务调度器加锁、使用信号量加锁、mutex方式
注意:一般不使用关中断的方式,除非任务十分简短,因为关中断是关闭所有的中断,包含滴答定时器中断,会使系统时钟出现问题
一般有俩种类型的信号量:二值信号量和多值信号量。二值信号量的值只能是0和1,多值信号量的值可以通过更改OS_SEM_CTR的定义修改为8、16、32位。
只有任务才允许使用信号量,ISR是不允许的。
信号量是内核对象,通过数据类型OS_SEM定义,应用中可以有任意多个信号量。
等待信号量 Pend 发送或释放信号量 Post
二进制信号量用于那些一次只能有一个任务使用的资源,比如IO设备
多值信号量用于某些资源可以被几个任务来使用

数据类型

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;
};

其中中间与调试有关的部分暂时不管
第一个为“Type”域,表明这定义的是一个信号量(UCOSIII每个内核对象都有Type域)
第二个为信号量的名字(UCOSIII每个内核对象都可以被赋予一个名字,为ASCII字符串组成,但必须以空字符结尾)
第三个为挂起队列若有多个任务等待信号量,信号量就会将这些任务放入其挂起队列中
OS_SEM_CTR为信号量中包含的一个信号量计数变值(若为1该信号量为二值信号量,若不为1该信号量为多值信号量)
最后一个是系统时间戳。

相关API函数

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

其中重点标注的三个API便是常用的三个,不仅仅是信号量,内建信号量、互斥信号量(Mutex)、内建互斥信号量消息队列也是一般只是用Create、Pend、Post三个函数。

注意事项

用信号量访问共享资源不会导致中断延迟。当任务在执行信号量所保护的共享资源时,ISR 或高优先级任务可以抢占该任务。
应用中可以有任意个信号量用于保护共享资源。然而,推荐将信号量用于I/O 端口的保护,而不是内存地址。
信号量经常被过度使用。很多情况下,访问一个简短的共享资源时不推荐使用信号量,请求和释放信号量会消耗CPU 时间。通过关/开中断能更有效地执行这些操作。为了说明,假设两个任务共享一个32 位的整数变量。第一个任务将这个整数变量加1,第二个任务将这个变量清零。考虑到执行这些操作用时很短,不需要使用信号量。执行这个操作前任务只需关中断,执行完毕后再开中断。若操作浮点数变量且处理器不支持硬件浮点操作时,就需要用到信号量。因为在这种情况下处理浮点数变量需较长时间。
信号量会导致一种严重的问题:优先级反转。
对于如何处理优先级翻转就需要使用互斥信号量

猜你喜欢

转载自blog.csdn.net/a568713197/article/details/83691301