跟着野火视频学习FreeRTOS——信号量

目录

1、信号量基本概念

1.1、二值信号量

1.2、计数信号量

1.3、互斥信号量

1.4、递归信号量

2、二值信号量应用场景

3、二值信号量运作机制

4、计数信号量运作机制

5、信号量控制块

6、常用信号量函数接口

6.1、创建信号量函数

1、创建二值信号量

2、创建计数信号量

6.2、信号量删除函数

6.3、信号量释放函数

1. xSemaphoreGive()(任务)

2. xSemaphoreGiveFromISR()(中断)

6.4 信号量获取函数

1. xSemaphoreTake()(任务)

2. xSemaphoreTakeFromISR()(中断)


1、信号量基本概念

是一种实现任务间通信的机制,可以实现任务之间同步或临界资源的互斥访问,常用于协助一组相互竞争的任务来访问临界资源。在多任务系统中,各任务之间需要同步或互斥实现临界资源的保护,信号量的功能可以为用户提供这方面的支持。

1.1、二值信号量

二值信号量既可以用于临界资源访问也可用于同步功能。

用作同步时,信号量在创建后应被置为空,任务一获取信号量而进入阻塞,任务二在某种套件发生后,释放信号量,于是任务以一获得信号量得以进入就绪态,如果任务一的优先级是最高的,那么就会立即切换任务,从而达到了两个任务间的同步。同样的,在中断服务函数中释放信号量,任务一也会得到信号量,从而达到任务与中断间的同步。

可以将二值信号量看作只有一个消息的队列,因此这个队列只能为空或满,我们在运用的时候只需要知道队列中是否有消息即可,而无需关注消息是什么。

1.2、计数信号量

二值信号量可以被认为是长度为1的队列,而计数信号量则可以被认为长度大于1的队列,信号量使用者依然不必关心存储在队列中的消息,只需关心队列是否有消息即可。

计数信号量是用来计数的,我们常将计数信号量用于事件技术与资源管理。每当某个事件发生时,任务或中断将释放一个信号量(信号量计数值加一),当处理事件时(一般在任务中处理),处理任务会取走该信号量(信号量数值减一),信号量的计数值则表示还有多少个事件没被处理。此外系统还有很多资源,我们也可以使用计数信号量进行资源管理,信号量的计数值表示系统中可用的资源数目,任务必须先获取到信号量才能获取资源访问权,当信号量的计数值为零时表示系统没有可用的资源,注意,在使用完资源的时候必须归还信号量,否则当计数值为0的时候任务就无法访问该资源了。

计数型信号量允许多个任务对其进行操作,但限制了任务的数量。当我们释放了这个资源,后面的任务才能对这个资源进行访问。

1.3、互斥信号量

就是特殊的二值信号量,由于其特有的优先级继承机制从而使它更适用于简单互锁,也就是保护临界资源。

用作互斥时信号量创建后可用信号量个数应该是满的,任务在需要使用临界资源时(临界资源是指任何时刻只能被一个任务访问的资源),先获取互斥信号量,使其为空,这样其他任务需要使用临界资源时就会因为无法获取信号量而进入阻塞,从而保证了临界资源的安全。

在操作系统中,我们使用信号量的很多时候是为了给临界资源建立一个标志,信号量表示了该临界资源被占用的情况。这样当一个任务在访问临界资源的时候,就会对这个资源信息进行查询,从而在了解资源被占用的情况之后再做处理,从而使得临界资源得到有效的保护。

1.4、递归信号量

对于已经获取递归互斥量的任务可以重复获取该递归互斥量,该任务拥有递归信号量的所有权。任务成功获取几次递归互斥量,就要返还几次,在此之前递归互斥量都处于无效状态,其他任务无法获取,只有持有递归信号量的任务才能获取与释放。

2、二值信号量应用场景

二值信号量是任务间、 任务与中断间同步的重要手段,信号量使用最多的一般都是二值信号量与互斥信号量(互斥信号量在下一章讲解) 。 为什么叫二值信号量呢?因为信号量资源被获取了,信号量值就是 0,信号量资源被释放,信号量值就是 1,把这种只有 0 和 1 两种情况的信号量称之为二值信号量。
 

3、二值信号量运作机制

创建信号量时, 系统会为创建的信号量对象分配内存,并把可用信号量初始化为用户自定义的个数, 二值信号量的最大可用信号量个数为 1。

二值信号量获取, 任何任务都可以从创建的二值信号量资源中获取一个二值信号量,获取成功则返回正确, 否则任务会根据用户指定的阻塞超时时间来等待其它任务/中断释放信号量。 在等待这段时间,系统将任务变成阻塞态, 任务将被挂到该信号量的阻塞等待列表中。

在二值信号量无效的时候,假如此时有任务获取该信号量的话,那么任务将进入阻塞状态。

假如某个时间中断/任务释放了信号量,其过程具体见图 18-2,那么,由于获取无效信号量而进入阻塞态的任务将获得信号量并且恢复为就绪态。

4、计数信号量运作机制

计数信号量可以用于资源管理,允许多个任务获取信号量访问共享资源,但会限制任务的最大数目。访问的任务数达到可支持的最大数目时,会阻塞其他试图获取该信号量的任务,知道有任务释放了信号量。

虽然计数信号量允许多个任务访问同一个资源,但是也有限定,比如某个资源限定只能有3个任务访问,那么第四个任务访问时,会因为获取不到信号量而进入阻塞,等到有任务释放掉该资源的时候,,第四个任务才能获取到信号量 从而进行资源的访问

5、信号量控制块

信号量 API 函数实际上都是宏,它使用现有的队列机制, 这些宏定义在 semphr.h 文件中, 如果使用信号量或者互斥量,需要包含 semphr.h 头文件。 所以 FreeRTOS 的信号量控制块结构体与消息队列结构体是一模一样的, 只不过结构体中某些成员变量代表的含义不一样而已。

6、常用信号量函数接口

6.1、创建信号量函数

1、创建二值信号量

xSemaphoreCreateBinary()用于创建一个二值信号量, 并返回一个句柄。
使 用 该 函数 创 建 的 二 值信 号 量 是 空的 , 在 使 用函 数xSemaphoreTake()获取之前必须先调用函数 xSemaphoreGive()释放后才可以获取。如果是使用老式的函数 vSemaphoreCreateBinary()创建的二值信号量,则为 1, 在使用之前不用先释放 。
 

2、创建计数信号量

xSemaphoreCreateCounting ()用于创建一个计数信号量。
其 实 计 数 信 号 量 跟 二 值 信 号 量 的 创 建 过 程 都 差 不 多 , 其 实 也 是 间 接 调 用xQueueGenericCreate()函数进行创建。

6.2、信号量删除函数

vSemaphoreDelete()用于删除一个信号量,包括二值信号量,计数信号量,互斥量和递归互斥量。 如果有任务阻塞在该信号量上,那么不要删除该信号量。
 

6.3、信号量释放函数

与消息队列的操作一样,信号量的释放可以在任务、中断中使用。

当信号量有效的时候, 任务才能获取信号量。

1. xSemaphoreGive()(任务)


xSemaphoreGive()是一个用于释放信号量的宏, 真正的实现过程是调用消息队列通用发送函数。

2. xSemaphoreGiveFromISR()(中断)


用于释放一个信号量,带中断保护。
带中断保护的信号量释放其实也是一个宏,真正调用的函数是 xQueueGiveFromISR ()。


6.4 信号量获取函数


与消息队列的操作一样,信号量的获取可以在任务、中断(中断中使用并不常见) 中使用。

1. xSemaphoreTake()(任务)

xSemaphoreTake()函数用于获取信号量,不带中断保护。
其实获取信号量是一个宏,真正调用的函数是 xQueueGenericReceive ()。

2. xSemaphoreTakeFromISR()(中断)

xSemaphoreTakeFromISR()是函数 xSemaphoreTake()的中断版本,用于获取信号量, 是一个不带阻塞机制获取信号量的函数, 获取对象必须由是已经创建的信号量, 信号量类型可以是二值信号量和计数信号量。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值