FreeRTOS多任务之间的通信——四种信号灯

💡 原文中文,约6300字,阅读约需15分钟。
📝

内容提要

本文介绍了四种常见的信号灯:计数信号灯、二值型信号灯、互斥信号灯和递归互斥信号灯。计数信号灯用于限制线程访问数量,二值型信号灯用于同步线程运行,互斥信号灯用于确保多个线程不能同时访问共享资源,递归互斥信号灯提供递归互斥锁的API。每种信号灯都有相应的API函数和示例代码。

🔎

延伸解读

计数信号灯示例中的计数变化

文章示例中,计数信号灯最大计数值为5,初始值为1,初始化任务又调用xSemaphoreGive增加一次,因此初始可用计数为2。日志显示连续两次获取成功,之后两次获取失败,这与计数被耗尽后无法在10个节拍内获取相符。读者可借此理解计数信号灯如何限制同时访问数量。

二值信号灯示例体现的同步行为

二值信号灯示例中,接收任务以10个节拍超时等待,发送任务每4秒释放一次信号量。日志先出现多次获取失败,随后一次成功,说明接收任务在信号量未释放时会被阻塞或超时,直到发送任务触发信号量后才能继续。这展示了二值信号灯用于线程同步的典型方式。

互斥信号灯与二值信号灯的关键差异

文章指出互斥锁和二元信号量非常相似,但互斥锁包含优先级继承机制,通常用于确保多个线程不能同时访问共享资源,以避免竞态条件。二值型信号灯则更适用于同步线程运行。示例中互斥信号灯的获取和释放API与二值信号灯一致,但创建函数不同,读者应注意区分使用场景。

递归互斥信号灯的API特殊性

递归互斥信号灯没有像前几种那样被广泛使用,主要提供递归互斥锁的API。其创建函数为xSemaphoreCreateRecursiveMutex(),但获取和释放需使用xSemaphoreTakeRecursive()和xSemaphoreGiveRecursive(),与前面三种信号灯的获取释放函数不同。文章提醒读者在使用时注意API的对应关系。

❓

Q&A

FreeRTOS中计数信号灯的主要作用是什么?

计数信号灯主要用于限制线程的访问数量,确保共享资源的安全访问。当资源可用时,线程可以获取信号并使用资源;当资源不可用时,线程将被阻塞,直到资源再次可用。

二值型信号灯和互斥信号灯有什么区别?

二值型信号灯通常用于同步线程的运行,确保一个线程完成之前另一个线程无法继续执行;而互斥信号灯包含优先级继承机制,用于确保多个线程不能同时访问共享资源,以避免竞态条件。

如何创建计数信号灯?请给出函数原型和参数说明。

使用xSemaphoreCreateCounting()函数创建计数信号灯,原型为:xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )。uxMaxCount为最大计数值,uxInitialCount为初始计数值,返回信号量句柄,失败返回NULL。

递归互斥信号灯的获取和释放使用什么函数?

递归互斥信号灯使用xSemaphoreTakeRecursive()获取,使用xSemaphoreGiveRecursive()释放。获取函数参数为互斥锁句柄和等待时钟滴答数,成功返回pdTRUE,超时返回pdFALSE;释放函数参数为互斥锁句柄,成功释放返回pdTRUE。

二值型信号灯通常用于什么场景?

二值型信号灯通常用于同步线程的运行,可以确保在一个线程完成之前另一个线程无法继续执行。它与互斥锁很相似,但适用于同步任务的场景。

互斥信号灯如何避免竞态条件?

互斥信号灯通过确保多个线程不能同时访问共享资源来避免竞态条件,并且它包含优先级继承机制,这有助于减少优先级反转问题。

🏷️

标签

➡️

继续阅读