FreeRTOS 操作系统学习
http://wiki.csie.ncku.edu.tw/embedded/FreeRTOS_Melot.pdf
4. 资源管理
4.1 二值信号量
二值信号量是同步任务的最简单有效方法,还存在一种更简单,但效率相对较低的轮询输入或查询资源的方法。二值信号量可以被认为是只有一个元素的队列,图7给出了其机制的示意。
4.1.1 二值信号量的处理
4.1.1.1 创建一个二值信号量
void vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore ); |
xSemaphore: 创建的信号。
4.1.1.2 获取信号
此操作等效于P()操作,如果与队列相比,则等效于Receive()操作。一个任务想获取某个信号必须等待它有效可用,在信号有效之前或延时满足之前任务将被阻塞。
portBASE_TYPE xSemaphoreTake( xSemaphoreHandle xSemaphore, portTickType xTicksToWait ); |
xSemaphore 需要获取的信号。
xTicksToWait 任务放弃使用信号,需要等到的时间(最小单位为始终节拍)。如果xTicksToWait等于MAX_DELAY并且INCLUDE_vTaskSuspend为1,则任务将不会停止等待。
如果获取操作在时间上成功完成,该函数将返回pdPASS。 如果不是,则返回pdFALSE。
4.1.1.1.3 给信号
可以将此操作与V()操作或与队列上的写操作进行类似。
portBASE_TYPE xSemaphoreGive( xSemaphoreHandle xSemaphore ); |
xSemaphore 需要写的信号。
如果给定操作成功,则该函数返回pdPASS;如果信号量已经可用,或者任务没有保留该信号,则该函数返回pdFAIL。
图表7 : 一个二值信号相当于只有一个元素的队列
4.2 互斥信号量
互斥锁旨在防止相互排斥或死锁。互斥锁的用法类似于二进制信号量,不同之处在于使用该信号量的任务必须将其返回。尽管可以访问某个资源但是必须取得相应的访问权限。任务取得资源的访问令牌便可以正常访问,结束后必须释放此令牌。同时,不能将其他令牌赋予互斥量。 图8很好地说明了这一点。
图8 互斥锁的常用示例
4.2.1 优先级继承
优先级继承实际上是二进制信号量和互斥量之间的唯一区别。当多个任务要求互斥信号时,互斥信号持有者任务的优先级将设置为最高等待优先级。这一机制尽管不能完全防止发生优先级反转现象,但它可以很好地帮助解决这个问题。使用互斥量会增加应用程序的全局复杂性,因此应尽可能避免使用。
4.3 计数信号量
信号量是一个非负整数计数。信号量通常用来协调对资源的访问,其中信号计数会初始化为可用资源的数目。然后,线程在资源增加时会增加计数,在删除资源时会减小计数,这些操作都以原子方式执行。如果信号计数变为零,则表明已无可用资源。计数为零时,尝试减小信号的线程会被阻塞,直到计数大于零为止。
计数信号量是一个值,该值随着信号量的增加而增加,而在获取信号量时减小。与具有一定数量元素的队列可比。 创建计数信号量后,可以将其初始化为任意次数。
4.3.1 计数信号量的历程
4.3.1.1 创建
如上所述,可以在有限的最大时间内获取计数信号量,并将其初始化为可用于任意数量的获取操作。 这些特征是在创建信号量时给出的。
xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount ); |
uxMaxCount 是计数信号量的最大信号量
uxInitialCount 创建的新信号量
若信号为空,返回 NULL ,创建失败通常是因内存不足或指针指向一个新的信号量。
4.3.1.2 获取&给予操作
P()和V()对信号量进行计数的操作 参考第4.1.1.2和4.1.1.3节。