
前言
最近在学习 ldd3,在写 scull 的时候,发现在输入 #include <asm/semaphore.h> 的时候,QtCreator 竟然没有路径补全提示,隐隐约约感觉遇到坑了。果然,新版本内核是没有这个文件的,搜寻了一番,发现新版本中应该变成了 <linux/semaphore.h>。本以为就这样解决了,却出了编译错误,init_MUTEX() 找不到。百度了一番,找到了不少文章,比如 这个 。根据百度的结果,应该是说init_MUTEX() 这个函数被废除了,网上的做法都是用 sema_init() 代替。也许是最近太无聊了,于是想把这一部分的前因后果搞清楚。
关于 init_MUTEX()系列函数的变迁
用关键字 init_MUTEX 在内核 git 日志中搜寻,发现在 2010 年 9 月之后有一波密集的 commits,将散在各处的 init_MUTEX 用sema_init替代,后来就没有过类似改动。这些 commits 的 tag 是 v2.6.37,于是查看了一下这个版本的所有提交,发现了下面这个:
author Thomas Gleixner <[email protected]> 2010-09-07 14:34:01 (GMT)
committer Thomas Gleixner <[email protected]> 2010-10-30 10:12:50 (GMT)
commit 4882720b267b7b1d1b0ce08334b205f0329d4615 (patch)
tree dd54880f84b7b7fb2bbdb529ffada434aca1e4d9
parent 45f4d0243525b6bc747c946937ced437b135a84d (diff)
semaphore: Remove mutex emulation
Semaphores used as mutexes have been deprecated for years. Now that
all users are either converted to real semaphores or to mutexes remove
the cruft.
Signed-off-by: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]> Cc: Christoph Hellwig <[email protected]>
LKML-Reference: <[email protected]>
正是这个提交最终废除了 DECLARE_MUTEX()、init_MUTEX()、init_MUTEX_LOCKED() 等函数(实则为宏)。此时的内核版本为 2.6.37, 而不是网上传的 2.6.25。
为了进一步搞清楚 semaphore.h 是何时从 <ams/semaphore.h> 转移到 <linux/semaphore.h> 的,继续往前搜寻,确定了下面的 commit:
author Matthew Wilcox <[email protected]> 2008-03-08 02:55:58 (GMT)
committer Matthew Wilcox <[email protected]> 2008-04-17 14:42:34 (GMT)
commit 64ac24e738823161693bf791f87adc802cf529ff (patch)
tree 19c0b0cf314d4394ca580c05b86cdf874ce0a167 /include/linux
parent e48b3deee475134585eed03e7afebe4bf9e0dba9 (diff)
Generic semaphore implementation
Semaphores are no longer performance-critical, so a generic C
implementation is better for maintainability, debuggability and
extensibility. Thanks to Peter Zijlstra for fixing the lockdep
warning. Thanks to Harvey Harrison for pointing out that the
unlikely() was unnecessary.
Signed-off-by: Matthew Wilcox <[email protected]>
Acked-by: Ingo Molnar <[email protected]>
这个 commit 以利于维护为理由,废除了位于 arch/ 中各个平台的 semaphore 实现,在 kernel/ 中实现了平台通用的 semaphore。此时的内核版本是 2.6.26,显然,网上所谓的“在 2.6.25 以后就再也找不到这个宏了”指的其实是 <asm/semaphore.h> 中的宏,2.6.25 之后这个文件都没了当然“找不到这个宏了”,但是其实只是变了个位置而已。
至于 <asm/semaphore.h> 产生于何时,在 linux 内核转移至 git 管理之前就已经存在,姑且认为生于上古时代。如此,init_MUTEX()系列函数的变迁历史算是理清了。
init_MUTEX()系列函数的废除过程
那到底 init_MUTEX() 是怎么废除的呢?这需要确定三个问题:
1. 何时开始废除
2. 何时完成废除
3. 废除的原因
第二个问题前面已经确定为 commit 4882720b267b7b1d1b0ce08334b205f0329d4615。回顾一下,其中提到 ”Semaphores used as mutexes have been deprecated for years”, 可见 2010 年 9 月那一次集中修改只是最后一波而已,类似动作可能几年前就开始了。于是继续向前查找,果然在大约 2006、2007 年期间出现了许多类似backlight:Convert semaphore -> mutex、[PATCH] sem2mutex: inotify 之类的 commit,所不同的是,这些提交大多是将 struct semaphore 换成了 struct mutex,头文件也换成了mutex.h。顺藤摸瓜,查到了创建mutex.h 的 commit:
author Ingo Molnar <[email protected]> 2006-01-09 23:59:19 (GMT)
committer Ingo Molnar <[email protected]> 2006-01-09 23:59:19 (GMT)
commit 6053ee3b32e3437e8c1e72687850f436e779bd49 (patch)
tree bb845004eb66554c569bc53a1efc87365c8a3cbe /include/linux
parent 2acbb8c657af86b2fa5b185f1d7048385e310585 (diff)
[PATCH] mutex subsystem, core
mutex implementation, core files: just the basic subsystem, no users of it.
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Arjan van de Ven <[email protected]>
这时的版本是 2.6.16,在这个版本里,mutex 子系统问世,原先许多基于 semaphore 的同步代码被替换为新的 mutex 实现,而由 semaphore 模拟的 ”mutex” 代码继续留在内核中,直到 2.6.37 版本才最后清理完毕。第一个问题也搞清楚了。
init_MUTEX()系列函数的废除原因
至于第三个问题,也就是废除的原因,其实基本已经能明白了。上古时代,正统的 mutex 还未出世,于是人们用 semaphore 模拟了 mutex,即所谓的“mutex emulation”。2006 年的 2.6.16 版本里,mutex 子系统出世,很多原先的代码开始转移到使用新的 mutex 子系统。直到 2010 年的 2.6.37 版本,用 semaphore 模拟的 mutex 被彻底清除。其实在 3.17 版本的 Documention/mutex-design.txt(这个文档在 3.16 之前主要描述 mutex 和 binary semaphore 的区别,3.16 开始改为 mutex 的一般性叙述,在 3.18 里干脆删除了) 里也有描述:
Mutexes are sleeping locks which behave similarly to binary semaphores, and were introduced in 2006[1] as an alternative to these.
至于二元 semaphore 和真正的 mutex 的区别,从含义来讲,主要在于 mutex 有一个所有者,只有其所有者可以将其解锁,而 semaphore 则无此限制,因此 mutex 才是真正意义上的互斥锁。这个系列 的文章从代码优化的角度谈了用 mutex 的理由。