正确使用的一个信号是从一个任务向另一个发信号。从每个使用被保护共享资源的任务来看,总是认为,一个互斥意味着获得和释放。相比之下,使用信号灯的任务不是发信号[在FreeRTOS里“发送”]就是在等信号[在FreeRTOS里“接收”]——不能同时。
互斥被用来保护共享资源。一个使用共享资源的任务获得互斥,接着释放互斥。当有另一个任务占据互斥时,没有一个任务可以获得这个互斥。这就是保证,在同一时刻仅有一个任务可以使用共享资源。
一个任务向另一个任务发信号时使用信号灯。以下引用Barr的文章:
For example, Task 1 may contain code to post (i.e., signal or increment) a particular semaphore when the "power" button is pressed and Task 2, which wakes the display, pends on that same semaphore. In this scenario, one task is the producer of the event signal; the other the consumer.
举例来说,任务一可能包含当“电源”按钮被按下时,发布(即,发信号或增加信号量)一个特定的信号灯的代码,并且唤醒显示屏的任务二,取决于同一个信号灯。在这种情况下,一个任务是发信号事件的制造者;另一个是消费者。
如果你是在信号灯和互斥有任何疑问,请查阅Michael的文章。
实现
FreeRTOS像队列一样来实现一个N元素的信号灯,这样就可以控制N个项。它没有去存储队列每项的任何实际数据;信号灯只关心有多少在队列的uxMessagesWaiting字段中被跟踪的队列记录,目前正被占用。当FreeRTOS的头文件semphr.h调用它的时候,它正在做“纯同步”。因此这个队列有一个零字节的项 (uxItemSize == 0)。每个信号灯uxMessagesWaiting字段递增或递减;没有项或数据的复制是需要的。
同信号灯一样,互斥也被实现为一个队列,不过有几个xQUEUE结构字段被用#defines重载:
/* Effectively make a union out of the xQUEUE structure. */
#define uxQueueType pcHead
#define pxMutexHolder pcTail
当互斥没有在队列中存储任何数据时,它不需要任何内部存储器,同样pcHead和pcTail字段也不需要。FreeRTOS设置uxQueueType字段(实际上的pcHead字段)为0来表明,这个队列正在被一个互斥使用。FreeRTOS使用重载的pcTail字段来实现互斥的优先级继承。
万一你不熟悉优先级继承,我将再次引用Michael Barr的话来定义它,这次是来自他的文章,“优先级倒置”:
[Priority inheritance] mandates that a lower-priority task inherit the priority of any higher-priority task pending on a resource they share. This priority change should take place as soon as the high-priority task begins to pend; it should end when the resource is released.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-30698-10.html
同我们一样
总在说数量