FreeRTOS的学习(八)——2.计数型信号量

23 篇文章 27 订阅

FreeRTOS的学习系列文章目录

FreeRTOS的学习(一)——STM32上的移植问题
FreeRTOS的学习(二)——任务优先级问题
FreeRTOS的学习(三)——中断机制
FreeRTOS的学习(四)——列表
FreeRTOS的学习(五)——系统延时
FreeRTOS的学习(六)——系统时钟
FreeRTOS的学习(七)——1.队列概念
FreeRTOS的学习(七)——2.队列入队源码分析
FreeRTOS的学习(七)——3.队列出队源码分析
FreeRTOS的学习(八)——1.二值信号量
FreeRTOS的学习(八)——2.计数型信号量
FreeRTOS的学习(八)——3.优先级翻转问题
FreeRTOS的学习(八)——4.互斥信号量
FreeRTOS的学习(九)——软件定时器
FreeRTOS的学习(十)——事件标志组
FreeRTOS的学习(十一)——任务通知


前言

信号量可以认为是队列的一种表达形式,他的存在给予了任务和任务,任务和中断之间的资源访问形式。

  1. 信号量常被用于控制对共享资源的访问和任务同步,可以对资源的变化进行计数,或者判断是否使用某资源等。
  2. 另外信号量还常用于任务同步,用于任务于任务或者中断与任务之间的同步。

FreeRTOS中具有非常多的信号量,比如计数信号量,二值信号量,互斥信号量和递归互斥信号量,其存在在某些情况下亦可以用队列的功能去替换。


1 计数型信号量简介

有些资料中也将计数型信号量叫做数值信号量,二值信号量相当于长度为 1 的队列,那么
计数型信号量就是长度大于 1 的队列。同二值信号量一样,用户不需要关心队列中存储了什么
数据,只需要关心队列是否为空即可。计数型信号量通常用于如下两个场合:

  1. 事件计数
    在这个场合中,每次事件发生的时候就在事件处理函数中释放信号量(增加信号量的计数值),其他任务会获取信号量(信号量计数值减一,信号量值就是队列结构体成员变量uxMessagesWaiting)来处理事件。在这种场合中创建的计数型信号量初始计数值为 0。
  2. 资源管理
    在这个场合中,信号量值代表当前资源的可用数量,一个任务要想获得资源的使用权,首先必须获取信号量,信号量获取成功以后信号量值就会减一。当信号量值为 0 的时候说明没有资源了。当一个任务使用完资源以后一定要释放信号量,释放信号量以后信号量值会加一。在这个场合中创建的计数型信号量初始值应该是资源的数量,

2 二值信号量的创建

二值信号量的创建函数如下:

  1. xSemaphoreCreateCounting(),使用动态方法创建计数型信号量。
  2. xSemaphoreCreateCountingStatic(),使用静态方法创建计数型信号量

函数的定义如下:

#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
    #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount )    xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
#endif

可以发现,真正干事的是xQueueCreateCountingSemaphore函数,这与二值信号量的创建函数不同,该函数在queue中定义如下:

#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )

    QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
                                                 const UBaseType_t uxInitialCount )
    {
        QueueHandle_t xHandle = NULL;
        if( ( uxMaxCount != 0 ) &&
            ( uxInitialCount <= uxMaxCount ) )
        {
            xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );

            if( xHandle != NULL )
            {
                ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;

                traceCREATE_COUNTING_SEMAPHORE();
            }
            else
            {
                traceCREATE_COUNTING_SEMAPHORE_FAILED();
            }
        }
        else
        {
            configASSERT( xHandle );
            mtCOVERAGE_TEST_MARKER();
        }

        return xHandle;
    }

#endif

该函数首先对函数的形参做了判断,也就是要求( uxMaxCount != 0 ) && ( uxInitialCount <= uxMaxCount ),相比于旧版的函数(没有这个判断)显然多了一重保障。
其次,调用了队列的创建函数xQueueGenericCreate,并给定队列的长度(uxMaxCount)以及队列生成的类型(queueQUEUE_TYPE_COUNTING_SEMAPHORE),其中信号量队列项的长度选择默认0(queueSEMAPHORE_QUEUE_ITEM_LENGTH)。
最后将初始计数值uxInitialCount赋值给uxMessagesWaiting,队列结构体的成员变量 uxMessagesWaiting 用于计数型信号量的计数。


3 信号量的释放和获取

释放和获取计数型信号量的方式与二值信号量相同,这里不再赘述。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LEODWL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值