通用互斥子系统 【ChatGPT】

简介: 通用互斥子系统 【ChatGPT】

通用互斥子系统

由Ingo Molnar mingo@redhat.com发起

由Davidlohr Bueso davidlohr@hp.com更新

互斥锁是什么?

在Linux内核中,互斥锁指的是一种特定的锁原语,它在共享内存系统上强制进行串行化,而不仅仅是指学术界或类似理论教材中所指的“互斥排斥”一般术语。互斥锁是一种睡眠锁,其行为类似于二进制信号量,并且于2006年1作为这些信号量的替代品被引入。这种新的数据结构提供了许多优势,包括更简单的接口,以及当时更小的代码(参见缺点)。

实现

互斥锁由在include/linux/mutex.h中定义的'struct mutex'表示,并在kernel/locking/mutex.c中实现。这些锁使用原子变量(->owner)在其生命周期内跟踪锁状态。字段owner实际上包含当前锁的所有者'struct task_struct *',因此如果当前未被占用,则为NULL。由于task_struct指针至少对齐到L1_CACHE_BYTES,低位(3位)用于存储额外状态(例如,如果等待列表非空)。在其最基本的形式中,它还包括一个等待队列和一个用于串行访问的自旋锁。此外,CONFIG_MUTEX_SPIN_ON_OWNER=y系统使用一个自旋MCS锁(->osq),在下面的(ii)中进行了描述。

在获取互斥锁时,可以采取三种可能的路径,具体取决于锁的状态:

  • 快速路径:尝试通过使用cmpxchg()原子地将所有者与当前任务进行比较交换来快速获取锁。这仅在无争用的情况下有效(cmpxchg()针对0UL进行检查,因此上述所有3个状态位必须为0)。如果锁有争用,它将进入下一个可能的路径。
  • 中间路径:也称为乐观自旋,尝试在锁所有者正在运行且没有其他准备运行的任务具有更高优先级(need_resched)时自旋以获取锁。其基本原理是,如果锁所有者正在运行,则很可能很快释放锁。互斥自旋者使用MCS锁排队,以便只有一个自旋者可以竞争互斥锁。
  • 慢路径:作为最后的手段,如果仍然无法获取锁,则任务将被添加到等待队列,并在解锁路径唤醒之前进入睡眠状态。在正常情况下,它会阻塞为TASK_UNINTERRUPTIBLE。

虽然从形式上来说内核互斥锁是可睡眠锁,但是路径(ii)使得它们在实际上更像是一种混合类型。通过简单地不中断任务并忙等待几个周期,而不是立即进入睡眠状态,这种锁的性能在许多工作负载中已经被证实显著提高。请注意,这种技术也用于读写信号量。

语义

互斥子系统检查并强制执行以下规则:

  • 一次只能有一个任务持有互斥锁。
  • 只有所有者可以解锁互斥锁。
  • 不允许多次解锁。
  • 不允许递归锁定/解锁。
  • 互斥锁必须仅通过API进行初始化(见下文)。
  • 任务不得在持有互斥锁的情况下退出。
  • 持有的锁所在的内存区域不得被释放。
  • 持有的互斥锁不得重新初始化。
  • 互斥锁不得在硬件或软件中断上下文中使用,例如任务队列和定时器。

当启用CONFIG DEBUG_MUTEXES时,这些语义将得到完全执行。此外,互斥锁调试代码还实现了许多其他功能,使锁调试更加容易和快速:

  • 在调试输出中打印互斥锁的符号名称。
  • 获取时的跟踪,函数名称的符号查找,系统中所有持有的锁的列表,以及它们的打印输出。
  • 所有者跟踪。
  • 检测自递归锁,并打印所有相关信息。
  • 检测多任务循环死锁,并打印所有受影响的锁和任务(以及仅这些任务)。

接口

静态定义互斥锁:

DEFINE_MUTEX(name);

动态初始化互斥锁:

mutex_init(mutex);

获取互斥锁,不可中断:

void mutex_lock(struct mutex *lock);
void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
int mutex_trylock(struct mutex *lock);

获取互斥锁,可中断:

int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass);
int mutex_lock_interruptible(struct mutex *lock);

获取互斥锁,可中断,如果减少到0:

int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);

解锁互斥锁:

void mutex_unlock(struct mutex *lock);

测试互斥锁是否被占用:

int mutex_is_locked(struct mutex *lock);

缺点

与其最初的设计和目的不同,'struct mutex'是内核中最大的锁之一。例如:在x86-64上它占用32字节,而'struct semaphore'占用24字节,rw_semaphore占用40字节。较大的结构大小意味着更多的CPU缓存和内存占用。

何时使用互斥锁

除非互斥锁的严格语义不适用和/或关键区域阻止锁被共享,否则始终优先选择它们而不是任何其他锁原语。

相关文章
genalloc/genpool 子系统 【ChatGPT】
genalloc/genpool 子系统 【ChatGPT】
162 11
|
开发框架 安全 .NET
TEE(可信执行环境)子系统 【ChatGPT】
TEE(可信执行环境)子系统 【ChatGPT】
|
Linux API 芯片
GPIO子系统驱动程序 【ChatGPT】
GPIO子系统驱动程序 【ChatGPT】
|
Linux API 虚拟化
PCI总线子系统 【ChatGPT】
PCI总线子系统 【ChatGPT】
|
Linux API 索引
PHY 子系统 【ChatGPT】
PHY 子系统 【ChatGPT】
|
Linux 测试技术 API
PINCTRL(PIN CONTROL)子系统 【ChatGPT】
PINCTRL(PIN CONTROL)子系统 【ChatGPT】
|
2月前
|
机器学习/深度学习 数据采集 人工智能
从ChatGPT到文心一言:AI为什么能“懂人话”?——大语言模型的底层逻辑揭秘
从ChatGPT到文心一言:AI为什么能“懂人话”?——大语言模型的底层逻辑揭秘
275 9
|
5月前
|
传感器 存储 人工智能
ChatGPT让AI展现‘智能’魅力,函数调用和RAG如何助力迈向AI Agent?
本文由AI产品专家三桥君探讨了AI从被动响应到主动决策的演进路径,重点分析了函数调用和RAG技术在构建AI Agent中的关键作用。文章梳理了大模型能力的迭代(原生能力与涌现能力),技术演进的三个阶段(提示工程→函数调用→RAG),并提出AI Agent需具备环境感知、推理决策和行动执行的核心要素。AI产品专家三桥君认为,未来AGI需突破跨领域学习、实时更新和安全性挑战,最终实现如"贾维斯"般的智能伙伴。
196 1
ChatGPT让AI展现‘智能’魅力,函数调用和RAG如何助力迈向AI Agent?
|
5月前
|
机器学习/深度学习 人工智能 文字识别
浏览器AI模型插件下载,支持chatgpt、claude、grok、gemini、DeepSeek等顶尖AI模型!
极客侧边栏是一款浏览器插件,集成ChatGPT、Claude、Grok、Gemini等全球顶尖AI模型,支持网页提问、文档分析、图片生成、智能截图、内容总结等功能。无需切换页面,办公写作效率倍增。内置书签云同步与智能整理功能,管理更高效。跨平台使用,安全便捷,是AI时代必备工具!
376 8
|
10月前
|
人工智能 Linux API
Omnitool:开发者桌面革命!开源神器一键整合ChatGPT+Stable Diffusion等主流AI平台,本地运行不联网
Omnitool 是一款开源的 AI 桌面环境,支持本地运行,提供统一交互界面,快速接入 OpenAI、Stable Diffusion、Hugging Face 等主流 AI 平台,具备高度扩展性。
1009 94
Omnitool:开发者桌面革命!开源神器一键整合ChatGPT+Stable Diffusion等主流AI平台,本地运行不联网

热门文章

最新文章