深层次探讨mutex与semaphore之间的区别(上)

简介: 看过Linux内核的同学都知道,Linux内核中除了有semaphore之外,还有一个mutex lock。前者我们的操作系统教科书称之为信号量,后者不知道教科书有没有具体的名称,但是在Linux内核中,它的称谓是"互斥锁"或者“互斥体”(总 之,称谓不是问题)。
看过Linux内核的同学都知道,Linux内核中除了有semaphore之外,还有一个mutex lock。前者我们的操作系统教科书称之为信号量,后者不知道教科书有没有具体的名称,但是在Linux内核中,它的称谓是"互斥锁"或者“互斥体”(总 之,称谓不是问题)。为了提升一下本帖的理论密度,特从Wiki中摘录一段关于semaphore的描述:

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源码中也可以看到这其中某些细微之处的区分。

*注:昨天写这个帖子时手头没有操作系统方面的书籍拿来参考,今天我翻了一下《现代操作系统》(陈向群等译,机械工业出版社  1999年11月第1 版), 关于这个话题,书里明确提到的只有"2.2.5 信号量",至于mutex,书中并没有作为一个独立的概念提出来,只是在讲信号量时提到了上面所说的binary semaphore,并且说“信号量mutex(应该是指binary semaphore)用于互斥...互斥是避免混乱所必需的操作...信号量的另一种用途是用于实现同步(synchronization)。信号量 full和empty用来保证一定的事件顺序发生或不发生。在本例中,它们保证缓冲区满的时候生产者停止运行,或者当缓冲区空的时候消费者停止运行。这种 用法与互斥是不同的” --- P30-31 *

OK,理论上的概念有了,那么就来看看实际当中Linux下的semaphone到底长的啥样。以下是semaphore在Linux源码中的定义,源码来自3.2.9:


  1. /* Please don't access any members of this structure directly */
  2. struct semaphore {
  3.         raw_spinlock_t lock;
  4.         unsigned int count;
  5.         struct list_head wait_list;
  6. };
如果count=1的话,那么semaphore就可以用来进行互斥操作了,早先内核源码中曾有一个专门的宏用来定义一个count=1的信号量DECLARE_MUTEX:

  1. #define DECLARE_MUTEX(name) \
  2.             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完全相同。


那么既然count=1的信号量可以用来完成mutex lock的功能,那么内核何必再多此一举弄出个mutex lock出来呢?


目录
相关文章
|
存储 缓存 算法
Linux 的 workqueue 机制浅析
## Intro workqueue 是 Linux 中非常重要的一种异步执行的机制,本文对该机制的各种概念,以及 work 的并行度进行分析,以帮助我们更好地**使用**这一机制;对 workqueue 机制并不陌生的读者也可以直接跳到第四节,即 "Concurrency" 小节,了解 workqueue 机制中 work 的并行度 以 v2.6.36 为界,workqueue 存在两个不
2148 0
Linux 的 workqueue 机制浅析
SpringBoot+支付宝:实现沙箱支付全过程
SpringBoot+支付宝:实现沙箱支付全过程
1159 0
|
9月前
|
人工智能 运维 安全
阿里云先知安全沙龙(上海站) ——终端安全对抗及防护
终端安全现状面临多重挑战,包括传统签名技术失效、新型无文件攻击频发、专业人才匮乏、分支机构安全管理不足等。企业终端覆盖不全、日志缺失、策略更新依赖厂商,导致运营排查困难。钓鱼攻击手法愈发精细,静态和动态对抗加剧,攻击者利用正常权限入侵,窃取凭据。Web3技术发展使加密货币成为新目标,职业黑客盯上个人钱包和交易公司。防护升级需涵盖预防、检测、响应和运营四个阶段,借助AI和威胁情报降低告警量,提升整体安全水平。
|
NoSQL Shell 容器
Cgroup Freezer 【ChatGPT】
Cgroup Freezer 【ChatGPT】
crash —— 查看进程的内核栈的内容
crash —— 查看进程的内核栈的内容
|
存储 算法 Linux
操作系统中的内存管理:从原理到实践
本文深入探讨了操作系统中至关重要的内存管理机制,揭示了从理论到实现的复杂过程。通过分析内存分配、虚拟内存以及分页和交换等概念,本篇文章旨在为读者提供对现代操作系统内存管理技术的全面理解。结合最新的技术动态和研究成果,文章不仅阐述了内存管理的基本原理,还讨论了其在实际操作系统中的应用和优化策略。
243 1
|
Windows
Windows——WMIC命令简单使用[windows获取private bytes]
Windows——WMIC命令简单使用[windows获取private bytes]
178 0
|
消息中间件 存储 网络协议
超硬核,基于mmap和零拷贝实现高效的内存共享(下)
超硬核,基于mmap和零拷贝实现高效的内存共享
|
前端开发 安全 Java
SpringBoot线程池ThreadPoolExecutor极简教程
ThreadPoolExecutor 是 java.util.concurrent 包下的一个类,在jdk1.5版本引入,帮助开发人员管理线程并方便地执行并行任务。 通俗来说,ThreadPoolExecutor 的作用是生产和管理线程池的,可以通过调用其 execute 方法和 submit 方法执行多线程任务。
1810 0
SpringBoot线程池ThreadPoolExecutor极简教程
|
JSON Java 数据格式
Java基础之Optional类(JDK1.8新特性)
Optional是一个容器,它可以保存类型T的值,或者仅仅保存null,Optional类主要是用来避免空指针异常(NPE),其提供的一系列的方法配合Lambda表达式可以让代码更加清晰,语义化,以及避免了空指针异常的问题,这里要注意是避免空指针异常,而不是避免返回null。
1330 1