"互斥(mutext)和旗语(semaphore)之间有什么不同?"这样的问题简短而有力,但要回答却相当困难.即使有经验的实时操作系统(RTOS)用户在区别如何正确使用mutex和semaphore时也存在着困难.
但这一点很不幸而且很危险,因为无任这两种原生RTOS中的哪一种被错误使用,都会导致嵌入式系统出现意想不到的错误,特别是这些系统为有关生命安全的产品时.
有关mutex和semaphore的荒诞说法是它们是相似的,甚至是可以互换的.正确的事实是尽管mutex和semaphore在它们的执行上有相似之处,但是我们还是应该在使用它们时加以区别对待.
最普遍(但也是不正确)的答案是:mutex和semphore非常相似,它们只有一个区别,那就是semaphores的计数可以超过1. 差不多所有的工程师都能正确的理解:mutex是一个二进制标志,可以通过它来确保执行流在代码关键区(critical section of code)互相排斥,从而对共享资源加一保护.但当他们被要求进一步回答如何使用"计算方法semaphore"的方式时,大部分工程师的回答就如同教科书书一般的刻板---semaphore用于保护多重同类资源.
通过类比办法,我们很容易解释为什么"多重资源"场景是有缺陷的.如果你认为一个mutex是由操作系统拥有的关键值的话,我们可以很容易地将个别的mutex比喻是城市咖啡店中一间浴室的钥匙.如果你想使用浴室,却找不到钥匙,你就必须在一个队列中等候.同样地,mutex则协串行化多项任务,以取得全域资源的共享,并且为等待队列中的任务分配一个静候其循序渐进的位置.
但这种简单的资源保护协议并不使用于两间相同浴室的情况.如果把一个semaphore概括为一个mutex,使其能保护两个或更多相同的资源,那么在我们的比喻中,它就象是放着两把相同钥匙的蓝子,你可以用任何一把打开任何一扇浴室的门.
因此,semaphore本身并不能解决多个相同资源的问题.咖啡店中的客人可能只知道有一把钥匙,但并不知道哪间浴室可用.如果你试图以此方式使用semaphore,你将会发现需要更多的状态信息---它们通常是由不同的mutex所保护的共享资源.
正确使用semaphore是为了使信号从一项任务传至另一项任务.mutex意味着取得与释放,使用受保护共享资源的每一次任务都是以这样的顺序进行.相比之下,使用semaphore的任务通常不是发送信号,就是进入等待状态,不可能同时发生.
例如,任务1可能包含程序代码,当按下"电源"(power)按钮时,即可提出(如发送信号或增量)一个特别的semaphore; 任务2则依据相同的semaphore而用于唤醒显示器. 在这种情况下,其中一项任务是信号的生产者,另一项任务是信号的消费者.
用一个例子来做总结,首先展示如何使用mutex:
/* Task 1 */
mutexWait(mutex_mens_room);
// Safely use shared resource
mutexRelease(mutex_mens_room);
/* Task 2 */
mutexWait(mutex_mens_room);
// Safely use shared resource
mutexRelease(mutex_mens_room);
相应地,你总是采用下列方法使用semaphore:
/* Task 1 - Producer */
semPost(sem_power_btn); // Send the signal
/* Task 2 - Consumer */
semPend(sem_power_btn); // Wait for signal
重要的是,semaphores可以被interrupt service routine(ISR)中断服务程序用来向task发送信号.发送一个semaphore是一个非阻塞的RTOS行为,并且ISR安全.因为这种技术排除了在task级别的为了是中断不使能而引起的错误的可能性,从ISR中发出信号是一种使嵌入式软件更加可靠的设计方式.
http://www.embedded.com/columns/guest/210605040?printable=true
http://www.eettaiwan.com/ART_8800557420_676964_NT_a22f6436.HTM