内核中各种同步机制(自旋锁大内核锁顺序锁等)

linux内核学习12:Linux内核中的同步机制,进程的同步同步机制,线程的同步机制 1. 什么是同步,为什么要同步,什么是互斥 1.1 同步和互斥 同步:用于实现控制多个进程按照一定的规则或顺序访问某些系统资源的机制。 互斥:实现控制某些系统资源在任意时刻只能允许一个进程访问的机制。互斥是同步机制中的一种特殊情况。 1.2 为什么要同步     在操作系统引入了进程概念,进程成为调度实体后,系统就具备了并发执行多个进程的能力,但也导致了系统中各个进程之间的资源竞争和共享。另外,由于中断、异常机制的引入,以及内核态抢占都导致了这些内核执行路径(进程)以交错的方式运行。对于这些交错路径执行 阅读详情

 

原子操作

 
原子操作是由编译器来保证的,保证一个线程对数据的操作不会被其他线程打断。
 

自旋锁

 
原子操作只能用于临界区只有一个变量的情况,实际应用中,临界区的情况要复杂的多。对于复杂的临界区,Linux 内核提供了多种方法,自旋锁就是其一。

自旋锁的特点就是当一个线程获取了锁之后,其他试图获取这个锁的线程一直在循环等待获取这个锁,直至锁重新可用。由于线程一直在循环获取这个锁,所以会造成 CPU 处理时间的浪费,因此最好将自旋锁用于很快能处理完的临界区。

自旋锁使用时两点注意:

  1. 自旋锁是不可递归的,以为自选锁内部关了抢占,递归的话最深层级的函数调用尝试获取自旋锁但是由于第一层级函数调用还没释放,所以会一直死自旋下去。
  2. 线程获取自旋锁之前,要禁止当前处理器上的中断。(事实上,spin_lock() 函数内部会自己做这个)。

 

小知识:为什么自旋锁调用底层不仅关中断而且关抢占?

关中断是因为中断处理程序有可能重入已获得自旋锁的代码段,造成递归死锁。

但是关了中断,时钟中断也关了,那么时间片无法计算了,不会调度了,为什么还要关抢占?

关抢占是因为虽然时钟中断被关掉,但是 Linux 有两种调度策略,SCHED_FIFO 和 SCHED_RR,FCHED_FIFO 是简单的队列调度,并没有时间片的限制,先来先运行,除非是阻塞或者主动让出(yield),否则一直占用 CPU,即使关中断也不能阻止优先级高的进程被调度运行。

 
中断处理下半部操作中使用尤其需要小心:

  1. 下半部处理和进程共享上下文数据时,由于下半部的处理可以抢占进程上下文的代码,所以进程上下文在对共享数据加锁前要禁止下半部的执行,解锁时再允许下半部执行。
  2. 中断处理程序(上半部)和下半部处理共享数据时,由于中断处理(上半部)可以抢占下半步的执行,所以下半部在对共享数据加锁前要禁止中断处理(上半部),解锁时再允许中断的执行。
  3. 同一种 tasklet 不能同时运行,所以同类 tasklet 中的共享数据就不需要保护。
  4. 不同类 tasklet 中共享数据时,其中一个 tasklet 获得锁后,不用禁止其他 tasklet 的执行。
  5. 同类型或者非同类型的软中断在共享数据时,也不用禁止下半部,因为在同一个处理器上不会有软中断相互抢占的情况。
     

读写自旋锁

 

  1. 读写自旋锁除了和普通自选锁一样有自旋特性外,还有以下特点,读锁之间是共享的,即一个线程持有了读锁之后,其他线程也可以以读的方式持有这个锁。
  2. 写锁之间是互斥的,即一个县城持有了写锁之后,其他线程不能以读或者写的方式持有这个锁。
  3. 读写锁之间是互斥的,即一个县城持有了读锁之后,其他线程不能以写的方式持有这个锁。

用法:

DEFINE_RWLOCK(mr_rwlock);

read_lock(&mr_rwlock);
/*critical region, only for read*/
read_unlock(&mr_rwlock);

write_lock(&mr_lock);
/*critical region, only for write*/
write_unlock(&mr_lock);

 

信号量

 
信号量也是一种锁,和自旋锁不同的是,线程获取不到信号量的时候,不会像自旋锁一样循环区试图获取锁,而是进入睡眠,直至有信号量释放出来时,才会唤醒睡眠的线程,进入临界区执行。

由于使用信号量时,线程会睡眠,所以等待的过程不会占用 CPU 时间。所以信号量适用于等待时间较长的临界区。
信号量消耗 CPU 时间的地方在于使线程睡眠和唤醒线程。
如果(使线程睡眠 + 唤醒线程)的 CPU 时间 > 线程自旋等待 CPU 时间,那么可以考虑使用自旋锁。
信号量睡眠一般会进入 TASK_INTERRUPTIBLE 状态,因为另一个无法被信号唤醒。
 

小知识:二值信号量和 mutex 的区别?

区别在于 mutex 只能被统一线程加锁解锁,二值信号量可以被不同线程加锁解锁。

 

读写信号量

 
读写信号量和信号量的关系与读写自旋锁和自旋锁的关系差不多。
 

互斥量

 

问题:互斥体也是一种可以用于睡眠的锁,嗯?为什么?为什么 spin_lock 不可以它可以?

在 mutex 锁定的临界区中调用 sleep(),那么底层会调用 schedule() 函数去进行进程调度,假设调度的新进程再次执行这段代码,由于 mutex 被之前的进程持有,该进程无法获得该锁,所以在 mutex_lock() 中又会调用 sleep() 去调用 schedule(),会切换到先前的进程,这样先前的进程迟早会 unlock(),不会死锁。所以mutex 中可以睡眠。而 spin_lock 就不一样了,调度的进程尝试获取 spin_lock,失败后会一直自旋,占据 CPU 不放,根本不会切换回去,所以死锁!所以在 spin_lock 的 lock() 函数中会关中断和抢占。

 
mutex 使用的场景比二值信号量严格,如下:

  1. mutex 计数值只能为 1,也就是说最多允许一个线程访问临界区。
  2. 必须在同一个上下文问加锁和解锁。
  3. 不能递归的上锁和解锁。
  4. 持有 mutex 时,进程不能退出。
  5. mutex 不能在中断或者下半部使用,也就是 mutex 只能在进程上下文中使用。
  6. mutex 只能通过官方 API 管理,不能自己写代码操作它 :)

 

知识点:中断上下文中为什么不能使用 mutex ?

因为 mutex 可能会引发睡眠或者进程调度,而进程调度是针对进程而言的,进程有 task_struct 结构体,中断上下文确不是一个进程,它没有 task_struct 结构体, 是不可调度的。没有 task_struct 的原因是中断调用频繁,并且处理程序很快,如果为中断维护一个 task_struct,那么对系统的吞吐量有所影响。同理,具有睡眠功能的如信号量也不能再中断上下文中使用。

 
mutex 和 spin_lock 如何选择:

需求建议加锁方法
低开销加锁优先使用spin_lock
短期锁定优先使用spin_lock
长期加锁优先使用mutex
中断上下文中加锁使用spin_lock
持有者需要睡眠使用mutex

mutex 比 spin_lock 开销多在进程上下文切换。中断上下文见上面小知识。
 

完成变量

 
完成变量名为 completion,就不具体介绍了,我倒是没见用过。
完成变量类似于信号量,当线程完成任务出了临界区之后,使用完成变量唤醒等待线程(更像 condition)。
 

大内核锁

 
一个粗粒度锁,Linux 过度到细粒度锁之前版本使用,现在几乎退役?
 

顺序锁

 
顺序锁在我的理解是一个部分优化的读写锁。它的特点是,读锁被获取的情况下,写锁仍然可以被获取。

使用顺序锁的读操作在读之前和读之后都会检查顺序锁的序列值。如果前后值不服,这说明在读的过程中有写的操作发生。那么该操作会重新执行一次,直至读前后的序列值是一样的。

do{
    /*读之前获取序列值*/
    seq = read_seqbegin(&foo);
    //do somethin
}while(read_seqretry(&foo, seq);  /*顺序锁foo此时的序列值不同则重来

 

禁止抢占

 
自旋锁同时关闭中断和抢占,但有时后只需要关闭抢占,我们来看一下它的方法:

方法描述
preempt_disable()增加抢占计数值,从而禁止内核抢占
preempt_enable()减少抢占计算,并当该值将为0时检查和执行被挂起的需要调度的任务
preempt_enable_no_resched()激活内核抢占但不再检查任何被挂起的需调度的任务
preempt_count()返回抢占计数

 

顺序和屏障

 
防止编译器优化我们的代码,让我们代码的执行顺序与我们所写的不同,就需要顺序和屏障。

函数如下:

方法描述
rmb阻止跨越屏障的载入动作发生重排序
read_barrier_depends()阻止跨越屏障的具有数据依赖关系的载入动作重排序
wmb()阻止跨越屏障的存储动作发生重排序
mb()阻止跨越屏障的载入和存储动作重新排序
smp_rmb()在SMP上提供rmb()功能,在UP上提供barrier()功能
smp_read_barrier_depends()在SMP上提供read_barrier_depends()功能,在UP上提供barrier()功能
smp_wmb()在SMP上提供wmb()功能,在UP上提供barrier()功能
smp_mb在SMP上提供mb()功能,在UP上提供barrier()功能
barrier阻止编译器跨越屏障对载入或存储操作进行优化

举例如下:

void thread_worker()
{
    a = 3;
    mb();
    b = 4;
}

上述用法就会保证 a 的赋值永远在 b 赋值之前,而不会被编译器优化弄反。在某些情况下,弄反了可能带来难以估量的后果。
 

如何选择

 
对于以上 10 中同步方法,应该如何选择?如图:
pic

 
 

参考:《Linux内核设计与实现》读书笔记(十)- 内核同步方法

【Linux内核】内核同步之(完成变量(completion)、大内核锁(BLK)、顺序所(seqlock)、禁止抢占、顺序和屏障(barriers)) 当处理多处理器之间或硬件设备之间的同步问题时,有时需要在你的程序代码中以指定的顺序发出读内存(读入)和写内存(存储)指令。在和硬件交互时,时常需要确保一个给定的读操作发生在其他读或写操作之前。另外,在多处理器上,可能需要按写数据的顺序读数据(通常确保后来以同样的顺序进行读取)但是​编译器和处理器为了提高效率,可能对读和写重新排序,​这样无疑使问题复杂化了幸好,所有可能重新排序和写的处理器提供了机器指令来确保顺序要 求。同样也可以​指示编译器不要对给定点周围的指令序列进行重新排序​。 阅读详情

相关推荐

逆变器技术解析:DDSRF双解耦在正负序分离中的关键作用

本文深入解析了DDSRF双解耦技术在逆变器正负序分离中的关键作用。通过建立正反旋转坐标系并利用交叉反馈解耦网络,DDSRF能快速、精准地分离电网电压中的正负序分量,从而显著提升锁相环在电网不平衡条件下的精度与系统稳定性,是现代高性能并网逆变器的核心算法之一。

m3n5b7v8c9x的博客 410

Linux内核锁的应用

一、锁的基本知识 1、锁是通过原子操作实现的,它本身不会导致竞态。 2、为什么要使用锁? 答:因为进程同步的存在,所以要使用锁。 用户空间: (1)用户程序会被调度器抢占和重新调度,用户程序可以在任何时刻被抢占,调度器会选择一个高优先级的进程到处理器上执行。 (2)SMP的存在使得多个处理器同时执行代码。 内核空间: 中断:中断处理程序可能随时打断当前正在执行的代码。 软中断和tasklet:内核...

静虚待令,有物混成 867

LEAP模型—低排放分析平台

LEAP 正在迅速成为进行综合资源规划、温室气体 (GHG) 缓解评估和低排放发展战略 (LEDS) 的国家的事实标准,尤其是在发展中国家,许多国家也选择使用 LEAP 作为其承诺的一部分向联合国气候变化框架公约(UNFCCC)报告。至少有 32 个国家使用 LEAP 来创建能源和排放情景,这些情景是其国家自主气候变化贡献计划 (INDC) 的基础:具有历史意义的巴黎气候协议的基础旨在表明各国开始经济脱碳的意图和投资于气候适应力。

weixin_54697010的博客 3280

关于Linux同步机制知识点整理

内核抢占是指内核在某些情况下可以抢占正在运行的进程或线程,以保证内核的响应能力和稳定性。内核抢占通常发生在中断处理程序中,当中断处理程序需要执行一些紧急的操作时,可以抢占正在运行的进程或线程,以保证中断处理程序的及时响应。在多线程编程中,需要考虑线程安全性,使用合适的同步机制和设计,来保证程序的正确性和可靠性。线程的使用可以提高程序的并发性和响应能力,但是需要注意线程安全性和同步机制的设计。同步机制是一种操作系统提供的机制,用于协调多个进程或线程之间的访问共享资源,防止出现竞态条件和死锁等问题。

瞌睡的洋葱的博客 1127

Pandas实战指南:从数据结构到清洗聚合的完整解析

在数据分析工作中,表格数据处理是最常见的需求,无论是电商运营还是量化交易,都离不开对结构化数据的清洗与转换。Python生态中,Pandas凭借Series与DataFrame两种核心数据结构,将数据标签与数值绑定,实现自动对齐,极大简化了数据操作流程。它不仅是数据清洗的利器,也是分组聚合、透视表分析和时间序列处理的基础工具。掌握Pandas,意味着能够高效完成从数据读取、缺失值处理、类型转换到分组统计的完整分析流水线,将重复性报表工作自动化。本文基于实际使用经验,系统梳理Pandas的核心概念、常用操作、

weixin_30768881的博客 258

Applied Energy期刊小白论文投稿模板-流程经验分享

Applied Energy期刊小白论文投稿模板-流程经验分享,Elsevier期刊(爱思唯尔)投稿流程

zzu_Flyer的博客 4万+

【005 基础知识】Linux同步机制?

使用同步机制(如互斥锁、信号量等),可以如不采取必要的同步措施,将会对一些关键数据结构进行交错访问和修改,从而导致这些数据结构状态的不一致,进而导致系统崩溃。因此,为了确保系统高效稳定有序地运行,linux 必须要采用同步机制。

kashine的博客 1332

9、横向束流光学:原理、模拟与耦合效应

本文系统介绍了横向束流光学中的关键概念,包括色度、色散、发射度、动量压缩因子以及四维耦合效应。通过MATLAB代码详细演示了相关参数的计算与模拟流程,展示了粒子在加速器中的运动特性及其对束流稳定性的影响。同时,讨论了如何通过磁铁配置优化束流光学性能,为加速器的设计与优化提供了理论基础和实践指导。

resnet7explorer的博客 118

Linux 中的同步机制

指哪些在同一时刻只允许被一个线程访问的软件或硬件资源。这种资源的特点是,如果有线程正在使用,其他进程必须等待直到该线程释放资源。指在每个线程中访问临界资源的那段代码。由于临界资源需要互斥访问,因此每个线程的临界区代码在执行时需要确保没有其他现成同事访问该资源。

私房菜 1831

Unreal5 从入门到精通之 如何实现 离线语音识别

本文介绍了如何使用离线语音识别插件 Offline Speech Recognition 进行本地语音转文本处理。该插件支持离线运行,用户可以通过下载并运行语言服务器(如 Vosk)来处理语音数据。文章详细说明了如何设置语言服务器、下载语言模型,并在虚幻引擎(UE)项目中配置麦克风和语音捕获。此外,还介绍了如何将 SoundWave 作为输入,以及如何通过节点将语音数据发送到语言服务器进行处理。最后,提供了相关文档链接以供进一步参考。

TxNet 906

【OpenClaw从入门到精通】第19篇:OpenClaw电商实战:从零搭建比价+库存监控+自动调价全自动化系统(2026实测附完整代码)

2026年OpenClaw成为全球最火开源项目,电商行业因其场景高频、数据标准化成为其核心落地领域。本文针对电商从业者面临的比价繁琐、库存混乱、调价滞后三大痛点,基于OpenClaw的“接入层-执行层-决策层”三层架构,从零拆解智能比价、多平台库存监控、动态自动调价三大核心场景的实现逻辑。文中包含完整的环境配置、技能安装、代码实现(含Python脚本与YAML配置)、执行结果验证,同时补充关键算法原理与避坑指南,兼顾新手入门与进阶提升。读者可直接参考本文实操流程,快速搭建属于自己的电商自动化系统,实现7×2

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 2238

Linux 同步机制

【代码】Linux 同步机制。

Kiris_king的博客 687

AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框架调研

在当今的人工智能时代,大模型技术的迅猛发展为各行各业带来了前所未有的变革。这些大模型,以其强大的语言理解和生成能力,正在逐步成为智能化应用的核心。然而,如何高效地利用这些大模型,构建出满足各种需求的应用,仍然是一个具有挑战性的问题。DB-GPT,作为一个开源的AI原生数据应用开发框架,应运而生,旨在简化大模型应用的开发过程,让构建智能化应用变得触手可及。本文将深入介绍DB-GPT的核心功能、关键特性,并通过实战操作,展示如何利用DB-GPT进行数据应用开发。DB-GPT是一个开源的AI原生数据应用开发框架。

寻道AI,探索AI无限可能! 1万+

linux内核同步方法汇总

原子操作 自旋锁 读-写自旋锁 信号量 读-写信号量 互斥量 完成变量 大内核锁 顺序锁

qq_38158479的博客 261

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Linux 内核的同步机制,第 1 部分 + 第二部分(转)

http://blog.youkuaiyun.com/jk198310/article/details/9264721 原文地址; Linux 内核的同步机制,第 1 部分 一、 引言 在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行...

weixin_34221332的博客 1207

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Linux 内核的同步机制,第 1 部分 + 第二部分

一、 引言 在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作、信号量(semaphore)、读写信号量(rw_sema

JK198310的专栏 1172

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

原子操作、信号量、读写信号量和自旋锁

本系列文章分两部分,第一部分详细地介绍了 Linux 内核中的同步机制:原子操作、信号量、读写信号量和自旋锁的API,使用要求以及一些典型示例。第二部分将详细介绍在Linux内核中的另外一些同步机制,包括大内核锁、读写锁、大读者锁、RCU和顺序锁。 一、 引言 在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共

不死亡灵,永垂不朽! 696

Linux内核中的各种锁

Linux内核中的各种锁在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作、信号量(semaphore)、读写信号量(rw_se

godleading的专栏 2万+

linux内核锁机制

linux内核锁机制1.介绍1.原子操作 1.介绍 在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作、信号量(semapho...

陆拾贰的博客 479

linux内核中锁有哪些,Linux内核中有哪些锁

Linux内核中的各种锁在LInux操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。linux内核在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作、信号量(semaphore)、...

weixin_31847389的博客 385

深入理解Linux内核(学习笔记)_第五章内核同步

可以把内核看作是请求进行响应的服务器,这些请求可能来自在CPU上执行的进程,也可能来自发出中断请求的外部设备。这些请求可能引起竞争条件,因此需要采用适当的同步机制对这种情况进行控制。 一.内核如何为不同的请求提供服务 ...

溯源守拙的博客 291

linux内核同步机制,Linux内核同步机制

而关于自旋锁的缺点?这里找到ibm一个文章信号量(semaphore):通用的 和读写的相对于自旋锁,它最大的特点就是允许调用它的线程进入睡眠/* Please don't access any members of this structure directly */struct semaphore {raw_spinlock_t lock;unsigned int ...

weixin_32247165的博客 215

《Linux内核设计与实现》读书笔记(十)- 内核同步方法【转】

转自:http://www.cnblogs.com/wang_yb/archive/2013/05/01/3052865.html 内核中提供了多种方法来防止竞争条件,理解了这些方法的使用场景有助于我们在编写内核代码时选用合适的同步方法, 从而即可保证代码中临界区的安全,同时也让性能的损失降到最低。 主要内容: 原子操作 自旋锁 读写自旋锁 信号量 读写信号量 互斥体 ...

weixin_34233679的博客 102

c++ 读写锁_linux中有哪些锁

Linux内核中的各种锁在LInux操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。linux内核在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作、信号量(semaphore)、...

weixin_39943547的博客 362
上一篇: 中断下半部的三种机制
下一篇: 剖析Disruptor:为什么会这么快?(二)神奇的缓存行填充
FreeeLinux
博客等级 码龄11年 421粉丝 356原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值