FreeRTOS 快速入门(五)之信号量


一、信号量的特性

信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务之间同步或临界资源的互斥访问,其实信号量主要的功能就是实现任务之间的同步与互斥,实现的方式主要就是依靠队列(信号量是特殊的队列)的任务阻塞机制。

1、信号量跟队列的对比

差异列表如下:

队列 信号量
可以容纳多个数据,创建队列时有两部分内存: 队列结构体、存储数据的空间 只有计数值,无法容纳其他数据。
创建信号量时,只需要分配信号量结构体
生产者:没有空间存入数据时可以阻塞 生产者:用于不阻塞,计数值已经达到最大时返回失败
消费者:没有数据时可以阻塞 消费者:没有资源时可以阻塞

由上面的表格可以看出:信号量相比队列更节省空间,因为实现同步与互斥不需要传递数据,所以信号量没有队列后面的环形存储区,信号量主要就是依靠计数值 uxMessagesWaiting(在队列中表示队列现有消息个数,在信号量中表示有效信号量个数)。

其实,创建信号量就对应创建特殊队列,获取信号量就对应队列出队,释放信号量就对应队列入队,学好了队列就基本学好了信号量。

2、两种信号量的对比

信号量的计数值都有限制:限定了最大值。如果最大值被限定为 1,那么它就是二值信号量;如果最大值不是 1,它就是计数型信号量。

二值信号量 计算型信号量
被创建时初始值为 0 被创建时初始值可以设定
其他操作是一样的 其他操作是一样的

二、信号量

首先来看一下信号的种类,相关的信号量函数放在第三章。

1、二值信号量

所谓二值信号量其实就是一个队列长度为1,没有数据存储器的队列,而二值则表示计数值uxMessagesWaiting只有0和1两种状态(就是队列空与队列满两种情况),uxMessagesWaiting在队列中表示队列中现有消息数量,而在信号量中则表示信号量的数量。

  • uxMessagesWaiting 为 0 表示:信号量资源被获取了.
  • uxMessagesWaiting 为 1 表示:信号量资源被释放了

把这种只有 0 和 1 两种情况的信号量称之为二值信号量。

由于二值信号量就是特殊的队列,其实它的运转机制就是利用了队列的阻塞机,从而达到实现任务之间的同步与互斥(有优先级反转的缺陷)。

1.1 二值信号量用于同步

在多任务系统中,经常会使用二值信号量来实现任务之间或者任务与中断之间的同步,比如,某个任务需要等待一个标记,那么任务可以在轮询中查询这个标记有没有被置位,则任务在等待的过程也会消耗 CPU 的资源,如下所示:

// 任务一
void Task1Function(void *param)
{
   
   
	volatile int i = 0;
	while (1)  {
   
   
		for (i = 0; i < 10000000; ++i) {
   
   
			sumj++;
		}
	
		flagCalcEnd = 1;
		vTaskDelete(
### FreeRTOS 快速入门教程第部分内容 FreeRTOS是一款广泛应用于嵌入式系统的实时操作系统,其快速入门教程通常会分为多个部分逐步介绍核心概念和功能模块。根据已有的资料[^1],可以推测第部分内容可能涉及更深层次的任务管理、调度器配置以及任务间的通信机制。 #### 任务间通信与同步 在FreeRTOS中,任务间通信是一个重要主题,主要包括三种主要方式:任务通知、队列和信号量[^3]。这些机制各有特点,在实际应用中可以根据需求选择合适的工具: - **任务通知**:一种轻量级的通信方法,适合简单的状态传递或事件触发场景。 - **队列**:支持数据传输的功能,适用于需要在任务之间交换复杂消息的情况。 - **信号量**:主要用于资源锁定或任务同步,包括二值信号量和计数信号量两种形式。 这部分内容可能会详细介绍如何使用上述机制实现高效的多任务协作,并通过实例演示具体操作流程。 #### 实践案例分析 为了加深理解,许多教程会在这一阶段提供实践案例来展示FreeRTOS的实际应用场景[^2]。例如,“深入理解FreeROS队列之队列实战”章节就属于此类进阶内容之一,它不仅讲解理论知识还配有动手实验环节指导学员完成特定目标。 以下是创建并初始化一个简单队列的例子: ```c #include "FreeRTOS.h" #include "queue.h" // 定义队列句柄 QueueHandle_t xQueue; void vAFunction( void ) { const TickType_t xTicksToWait = pdMS_TO_TICKS( 100 ); // 创建具有十个整型空间大小的队列 xQueue = xQueueCreate( 10, sizeof( int ) ); if( xQueue != NULL ){ int xValueToSend = 99; // 向队列发送数值 if( xQueueSend( xQueue , &xValueToSend , xTicksToWait ) == pdPASS ){ // 发送成功后的处理逻辑... } }else{ // 队列创建失败错误提示... } } ``` 此代码片段展示了如何定义、创建以及向队列发送数据的过程。
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值