从0到1学习FreeRTOS:FreeRTOS 内核应用开发:(十一)信号量 NO.1 基本概念
目录
一、信号量基本概念:
1、二值信号量:
2、计数信号量:
3、互斥信号量:
4、递归信号量:
二、二值信号量应用场景:
三、二值信号量运作机制:
四、计数信号量运作机制:
五、信号量控制块:
一、信号量基本概念:
信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务之间同步或临界资源的互斥访问, 常用于协助一组相互竞争的任务来访问临界资源。在多任务系统中,各任务之间需要同步或互斥实现临界资源的保护,信号量功能可以为用户提供这方面的支持。
1、二值信号量:
① 二值信号量既可以用于临界资源访问也可以用于同步功能。
② 二值信号量和互斥量非常相似,但是有一些细微差别:互斥量有优先级继承机制,二值信号量则没有这个机制。这使得二值信号量更偏向应用于同步功能,而互斥量更偏向应用于临界资源的访问。
③ 用作同步时,信号量在创建后应被置为空,任务获取不到信号量从而进入阻塞状态。当任务/中断释放信号量后,任务获得信号量继续执行,形成同步。
④ 可以将二值信号量看作只有一个消息的队列,因此这个队列只能为空或满(因此称为二值),我们在运用的时候只需要知道队列中是否有消息即可,而无需关注消息是什么。
2、计数信号量:
① 二值信号量可以被认为是长度为1的队列,而计数信号量则可以被认为长度大于1的队列,信号量使用者依然不必关心存储在队列中的消息,只需关心队列是否有消息即可。
② 我们常将计数信号量用于事件计数与资源管理。
3、互斥信号量:
① 互斥信号量其实是特殊的二值信号量,由于其特有的优先级继承机制从而使它更适用于简单互锁,也就是保护临界资源。
② 在操作系统中,我们使用信号量的很多时候是为了给临界资源建立一个标志,信号量表示了该临界资源被占用情况。这样,当一个任务在访问临界资源的时候,就会先对这个资源信息进行查询,从而在了解资源被占用的情况之后,再做处理,从而使得临界资源得到有效的保护。
4、递归信号量:
递归信号量,可以重复获取调用的, 对于已经获取递归互斥量的任务可以重复获取该递归互斥量, 该任务拥有递归信号量的所有权。 任务成功获取几次递归互斥量, 就要返还几次,在此之前递归互斥量都处于无效状态, 其他任务无法获取, 只有持有递归信号量的任务才能获取与释放。
二、二值信号量应用场景:
任务与任务同步的应用场景
中断与任务同步的应用场景
三、二值信号量运作机制:
创建信号量时,系统会为创建的信号量对象分配内存,并把可用信号量初始化为用户自定义的个数, 二值信号量的最大可用信号量个数为1。
二值信号量获取,任何任务都可以从创建的二值信号量资源中获取一个二值信号量,获取成功则返回正确,否则任务会根据用户指定的阻塞超时时间来等待其它任务/中断释放信号量。在等待这段时间,系统将任务变成阻塞态,任务将被挂到该信号量的阻塞等待列表中。
在二值信号量无效的时候,假如此时有任务获取该信号量的话,那么任务将进入阻塞状态,见下图(图文来自野火论坛):
假如某个时间中断/任务释放了信号量,由于获取无效信号量而进入阻塞态的任务将获得信号量并且恢复为就绪态,其过程具体见下图:
四、计数信号量运作机制:
计数信号量可以用于资源管理,允许多个任务获取信号量访问共享资源,但会限制任务的最大数目。访问的任务数达到可支持的最大数目时,会阻塞其他试图获取该信号量的任务,直到有任务释放了信号量。见下图(图文来自野火论坛):
五、信号量控制块:
信号量 API 函数实际上都是宏,它使用现有的队列机制, 这些宏定义在 semphr.h 文件中, 如果使用信号量或者互斥量,需要包含 semphr.h 头文件。
① 如果控制块结构体是用于消息队列: uxMessagesWaiting 用来记录当前消息队列的消息个数; 如果控制块结构体被用于信号量的时候, 这个值就表示有效信号量个数,有以下两种情况:
如果信号量是二值信号量、互斥信号量,这个值是 1 则表示有可用信号量,如果是 0 则表示没有可用信号量。
如果是计数信号量,这个值表示可用的信号量个数,在创建计数信号量的时候会被初始化一个可用信号量个数 uxInitialCount,最大不允许超过创建信号量的初始值 uxMaxCount。
② 如果控制块结构体是用于消息队列: uxLength 表示队列的长度,也就是能存放多少消息; 如果控制块结构体被用于信号量的时候, uxLength 表示最大的信号量可用个数, 会有以下两种情况:
如果信号量是二值信号量、互斥信号量, uxLength 最大为 1,因为信号量要么是有效的,要么是无效的。
如果是计数信号量,这个值表示最大的信号量个数,在创建计数信号量的时候将由用户指定这个值 uxMaxCount。
③ 如果控制块结构体是用于消息队列: uxItemSize 表示单个消息的大小; 如果控制块结构体被用于信号量的时候,则无需存储空间,为 0 即可。