“In computer science, a semaphore is a variable or abstract data type that provides a simple but useful abstraction for controlling access by multiple processes to a common resource in a parallel programming environment.
A useful way to think of a semaphore is as a record of how many units of a particular resource are available, coupled with operations to safely (i.e., without race conditions) adjust that record as units are required or become free, and if necessary wait until a unit of the resource becomes available. Semaphores are a useful tool in the prevention of race conditions and deadlocks; however, their use is by no means a guarantee that a program is free from these problems. Semaphores which allow an arbitrary resource count are called counting semaphores, while semaphores which are restricted to the values 0 and 1 (or locked/unlocked, unavailable/available) are called binary semaphores (same functionality that mutexes have).”。
其中关键信息主要是“a semaphore is a data type for controlling access by multiple processes to a common resource in a parallel programming environment... Semaphores which allow an arbitrary resource count are called counting semaphores, while semaphores which are restricted to the values 0 and 1 (or locked/unlocked, unavailable/available) are called binary semaphores (same functionality that mutexes have)”,也即信号量在并行处理环境下对多个processes访问某个公共资源进行保护,后面提到的binary semaphore,本质上应该就是mutex了,从same functionality that mutexes have这句话来看,mutex和binary semaphore功能应该相同。从以上的文字中显然可以看到,相对mutex而言信号量的适用范围更广(mutex只是信号量的用途之一),这个我们接下来在后续的Linux源码中也可以看到这其中某些细微之处的区分。
struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
复制代码
因为我们知道在Linux内核源码中还有一个DEFINE_MUTEX宏,所以Marcin Slusarz同学认为DECLARE_MUTEX宏容易让人困惑,毕竟它其实只是定义了一个count=1的信号量,因此该同学早在08年就向内核社区提交了一个PATCH,要求Rename DECLARE_MUTEX to DEFINE_SEMAPHORE(https://lkml.org/lkml/2008/10/26/74),这个PATCH最终被社区所接受(应该是在2.6.35和2.6.39版本之间,2.6.39已经没有了DECLARE_MUTEX,取而代之的是DEFINE_SEMAPHORE,但2.6.35还有,我当时在写《深入Linux设备驱动程序内核机制》时,最早引用的是2.6.35的版本,虽然在写作的中晚期将内核版本切换到2.6.39并在定稿阶段曾试图将之前写的文档全部修正到39版,但是DECLARE_MUTEX的残留显然是条漏网之鱼...)。因为只是rename,所以DEFINE_SEMAPHORE的定义和原来的DECLARE_MUTEX完全相同。
"Why on earth do we need a new mutex subsystem, and what's wrong with semaphores?" 前面已经讲过,当struct semaphore中的成员变量为1,就可以用来实现mutex这种东西,而且内核也明确定义了DEFINE_SEMAPHORE宏将count初始化为1,信号量上的DOWN与UP操作就更不用说了,在内核中也都有很好的实现,难道这种binary semaphore机制还不能满足我们的要求吗,干嘛还非得弄一个新的mutex机制出来呢?
下面是Ingo同学对此的解释,他说“firstly, there's nothing wrong with semaphores. But if the simpler mutex semantics are sufficient for your code, then there are a couple of advantages of mutexes”,就是说,信号量在Linux中的实现是没任何问题的(上来先安抚一下大家躁动的心情),但是mutex的语义相对来说要较信号量要来得简单,所以如果你的代码若只是想对某一共享资源进行互斥访问的话,那么使用这种简化了的mutex机制可以带来如下的一坨好处。对这句话我的理解是,mutex将binary semaphore的实现简化了(the simper mutex),因此如果单纯从互斥的角度,用mutex会有很多好处。
接下来Ingo列出的一大堆使用mutex的好处,在这个帖子中我们将一条一条地来看,再结合内核源码,看看事实是否的确象他说的那样: - 'struct mutex' is smaller on most architectures: E.g. on x86, 'struct semaphore' is 20 bytes, 'struct mutex' is 16 bytes. A smaller structure size means less RAM footprint, and better CPU-cache utilization.