深入理解和实现RTOS_连载7_信号量机制概述
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
信号量机制概述
在实际的多任务应用中,任务间、任务和ISR间经常要同步彼此的执行步骤,内核大多通过信号量这种内核对象来实现这个功能。信号量是一种统称,常见的信号量主要有三种:二值信号量、计数信号量和互斥信号量,它们各有自己典型的使用模式。从使用目的角度考虑,作者更希望把互斥信号量和另外两种信号量的概念区分开来。
飞鸟RTOS目前支持二值信号量、计数信号量和互斥信号量。其中二值信号量和计数信号量是在一起设计实现的,而互斥信号量则是单独实现的。在本文的描述中,前两者经常统称为信号量,而后者被称为互斥量。本篇主要介绍二值信号量和计数信号量的概念、设计实现和典型的使用模式。
信号量的基本知识
信号量用于同步的时候就像交通灯,任务只有在获得许可的时候才可以运行,强调的是运行步骤;信号量用于互斥的时候就像一把钥匙,它强调只有获得钥匙的任务才可以运行,强调的是许可和权限。信号量只用于同步或者互斥操作,它不具备任何数据交换的功能。
二值信号量的概念
二值信号量只能取两个值,作为资源是否可用的标记,或者用来同步任务。当它被创建的时候,初始值可以在0或1中任选,这是根据应用的需要来设置的。需要注意的是二值信号量可以被任何任务或者ISR释放,甚至在它们从来没有获得过二值信号量的情况下。
二值信号量的状态
二值信号量通常拥有2种状态:可用和不可用。根据需要,二值当信号量可以被初始化成可用或者不可用。以初始状态为不可用为例,当有任务释放信号量时,它的状态转为可用。当有任务获得信号量后,它的状态随之变为不可用。随着任务对二值信号量的操作,它的状态在这2种情况下相互转换,符合有限状态机机制。
当二值信号量处于不可用的状态的时候,如果有任务来获取,那么该任务或者直接返回失败,或者阻塞到该二值信号量上,直到该二值信号量可用或者任务阻塞时限期满;当二值信号量处于可用状态的时候,如果有任务来释放信号量,那么该任务或者直接返回失败,或者阻塞到该信号量上。注意ISR操作信号量的时候,只能立刻返回操作结果,这是因为ISR 不能被阻塞。
下图描述了二值信号量的状态迁移和原因:
图4-1 二值信号量状态迁移图
任务阻塞队列
二值信号量具有任务阻塞的能力,名义上二值信号量拥有两个不同类型的任务阻塞队列,代表了获取信号量的任务阻塞队列和释放信号量的任务阻塞待队列。而实现上只需要一个任务阻塞队列就可以了,因为不可能同时阻塞这样的两个任务:一个不能获取信号量而另一个不能释放信号量。
需要注意的是,当二值信号量为不可用的时候,如果有任务处于二值信号量的任务阻塞队列中,说明当前二值信号量的任务阻塞队列是信号量获取任务队列。如果此时有任务释放二值信号量,可以直接从二值信号量的任务阻塞队列中找到一个合适的任务,并直接使得它获取信号量成功,同时二值信号量的状态不变。同理,在二值信号量可用的时候,如果有任务处于二值信号量的任务阻塞队列,说明当前二值信号量的任务阻塞队列是信号量释放任务队列, 假如此时有任务来获取信号量,可以从二值信号量的任务阻塞队列中找到一个合适的任务,并直接使得它释放信号量成功。此时二值信号量状态同样保持不变。
计数信号量的概念
计数信号量通常用来表示资源可用的个数。它提供一个计数器给任务或者ISR来使用,计数器的数值代表了还有多少个资源可以使用,数值0说明没有资源可供使用。任务或者ISR可以多次获取一个计数信号量,直到它的计数减小到0为止。和二值信号量一样,计数信号量可以被任何任务或者ISR释放,哪怕它们从来没有获得过该计数信号量。
计数信号量状态
计数信号量通常可以按照计数的多少来区分其状态。根据需要,计数信号量可以被初始化任何状态。以计数初始化为0为例,此时它处于不可获取,可以释放的状态。当有任务释放信号量时候,它转为1,即可以获取、可以释放的状态。当任务继续释放信号量,当计数达到最大的时候,它的状态为不可释放,可以获得的状态。随着计数信号量的获取和释放,计数信号量的状态在这3种情况下相互转换,符合有限状态机机制。下图描述了计数信号量的状态迁移和原因:
图4‐2 计数信号量状态迁移图
任务阻塞队列
计数信号量具有任务阻塞的能力,名义上计数信号量拥有两个不同类型的任务阻塞队列,代表了获取信号量的任务阻塞队列和释放信号量的任务阻塞待队列。而实现上只需要一个任务阻塞队列就可以了,因为不可能同时阻塞这样的两个任务:一个不能获取信号量而另一个不能释放信号量。
需要注意的是,当计数信号量为不可获取的时候,即计数为0的时候,如果有任务处于计数信号量的任务阻塞队列中,说明当前计数信号量的任务阻塞队列是信号量获取任务队列。如果此时有任务释放计数信号量,可以直接从计数信号量的任务阻塞队列中找到一个合适的任务,并直接使得它获取信号量成功,同时计数信号量的状态不变;同理,在计数信号量可获取、不可释放的时候,即计数达到最大的时候,如果有任务处于计数信号量的任务阻塞队列,说明当前计数信号量的任务阻塞队列是信号量释放任务队列, 假如此时有任务来获取信号量,可以从计数信号量的任务阻塞队列中找到一个合适的任务,并直接使得它释放信号量成功。此时计数信号量状态同样保持不变;当计数信号量的计数处于0和最大值之间时,此时计数信号量可以被获取也可以被释放,其任务阻塞队列中不会有任务被阻塞。
信号量的操作
常见信号量的操作主要包括以下几种:
功能 操作 功能
1create 信号量创建
2delete 信号量删除
3obtain 信号量获取
4release 信号量释放
5flush 信号量任务阻塞队列的刷新
6query 信号量状态查询
表 4‐1 信号量常见操作
z Create 信号量创建
信号量结构可以被系统分配或者初始化,在创建信号量时,用户可以指定信号量的
各种参数属性。比如针对多个任务在信号量上的阻塞和调度方式:既可以配置成