前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Linux内核37-内核数据的同步访问

Linux内核37-内核数据的同步访问

作者头像
Tupelo
发布于 2022-08-15 08:09:56
发布于 2022-08-15 08:09:56
93000
代码可运行
举报
文章被收录于专栏:嵌入式ARM和Linux嵌入式ARM和Linux
运行总次数:0
代码可运行

每一种技术的出现必然是因为某种需求。正因为人的本性是贪婪的,所以科技的创新才能日新月异。

1 内核数据的同步访问

前面,我们学习了这么多内核同步技术。那我们该怎么选择呢?选择不同的内核同步技术,可能对系统的性能影响很大。根据经验,基本可以遵守这么一条准则:尽可能高地保证系统的并发性

而系统的并发水平又依赖于两个关键的因素:

  • 可以并发访问的I/O设备数量;
  • 能够执行有效工作的CPU数量。

为了最大化I/O的吞吐量,中断禁止的时间应该尽可能短。我们知道,如果中断被禁止,I/O设备发出的IRQ信号会被PIC中断控制器临时性地忽略,也就不会相应I/O设备的请求。

为了使CPU的效率最大化,基于自旋锁的内核同步原语尽可能不用。因为,当CPU忙等待自旋锁被释放的时候,其实浪费了珍贵的机器执行周期。甚至更糟糕的是,自旋锁还会影响硬件Cache,强迫Cache失效,从而从内存中重新读取数据,刷新Cache,这大大降低了系统的整体性能。这就是为什么多核系统不能达到1+1=2的效果的原因。

让我们举几个例子来说明如何在保持高并发水平的同时还能实现同步:

  • 如果共享的数据结构是一个简单的整数,那么可以使用atomic_t类型的原子变量声明它。原子操作比自旋锁和禁止中断都快,它只是降低了并发访问数据的内核控制路径的执行速度。
  • 但是,往链表中插入元素就不是原子的,因为至少包含两个指针赋值操作。然而,内核有时候可以在不使用锁或禁止中断的前提下执行这种插入操作。比如,系统调用服务例程中,系统调用插入新元素到一个单链表中,而中断处理程序或可延时函数异步遍历这个列表,就无须锁的保护。

另外,在内核的实现代码中,我们经常需要对列表进行插入操作,通常使用指针赋值的方式实现,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
new->next = list_element->next;
list_element->next = new;

将上面的代码转换成汇编语言之后,就成为2条连续的原子指令操作。第1条指令建立新元素的next指针,但是不会修改列表。第2条指令将其存入对应的内存位置。假设,在这2条指令执行之间来一个中断信号,则中断处理程序看到的列表没有新元素;如果中断信号在第2条指令执行之后到来,则中断处理程序看到是的已经插入新元素的列表。任何一种情况,列表的数据都是正确的,没有被破坏的。但是,必须保证中断处理程序不会修改这个列表。如果其修改了列表,next指针很可能就会变成非法值。

更重要的是,这两条指令是由时序关系的。只有先创建了next指针,才能给其赋值;否则,操作不合法。所以,对于上面的代码,内核开发者应该保证它们的执行顺序,不会被编译器或者CPU控制单元破坏。否则,在两条赋值语句之间插入进来执行的中断服务程序,会发现一个被破坏了的列表。这时候,往往需要一个写内存屏障原语,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    new->next = list_element->next;
    wmb();
    list_element->next = new;

到这儿,很多人可能会纳闷:为什么我在编写内核代码或者驱动程序的时候,怎么几乎不使用wmb()之类的内存屏障呢?那是因为,Linux内核提供的操作函数API已经封装了内存屏障原语。所以,大部分时候我们不需要关心它。

通过上面的分析,我们可以得出的结论就是:尽可能提高系统的并发性,也就是压榨CPU能够有效工作的时间。为此,在保护要访问的数据的同时,尽可能不要选择自旋锁、信号量和关闭中断之类的加锁机制。因为它们往往让CPU处于无效工作时间中,降低系统的性能。

但是,许多时候我们别无选择,只能使用这些降低系统性能的加锁机制。当我们不得不面对的时候,我们又该如何抉择呢?

2 如何选择自旋锁、信号量和禁止中断

不幸的是,访问内核数据结构的形式远远比上面的示例复杂多了,迫使内核开发者不得不启动信号量、自旋锁和中断禁止这些锁原语。通常来讲,具体选择哪种加锁机制,取决于访问数据的是哪种内核控制路径,如下表所示。但需要注意的一点是,无论何时,内核控制路径请求一个自旋锁(包括读写锁,seqlock和RCU)时,都会禁止局部中断或者软中断,从而禁止内核抢占。

表5-8 不同内核控制路径访问的数据结构需要的锁

内核控制路径

单核系统

多核系统

异常处理程序

信号量

信号量

中断处理程序

禁止中断

自旋锁

可延时函数

无/自旋锁

异常处理程序+中断处理程序

禁止中断

自旋锁

异常处理程序+可延时函数

禁止软中断

自旋锁

中断处理程序+可延时函数

禁止中断

自旋锁

中断处理程序+可延时函数+异常处理程序

禁止中断

自旋锁

在了解这些不同的内核控制路径访问的数据结构应该如何保护之前,我们先来复习几个概念:

  1. 硬中断和软中断的区别 严格意义上来说,中断可以分为同步中断和异步中断。而所谓的同步中断肯定就是CPU自身产生的中断,也就是所谓的异常。比如,除零操作就会产生硬件错误,在嵌入式内核中很常见这之类的错误。对于这类错误,首先应该能避免就避免,这是我们嵌入式开发者或者内核开发者必须要考虑的工作;实在无法避免(有时候可能还要故意产生硬件异常,比如Linux就利用页错误做特殊处理),就要编写异常处理程序进行必要处理,比如发送信号给当前进程等。 对于异常,在此不做过多描述。所以,在此,所说的中断特指异步中断,主要用来服务I/O设备还有CPU之间的中断。为了及时响应外部I/O设备和其它CPU,中断直接打断CPU的执行,让其执行对应的中断处理程序。所以,中断处理程序必须占用CPU的时间极短,且不能发生阻塞操作,但允许嵌套中断执行。 但是,有时候,中断信号所引发的操作比较复杂,但是可以分为需要及时处理和可以延时处理的部分。对于需要及时处理的部分就交给中断处理程序直接处理就好了,也就是我们常说的概念-顶半部。而对于可延时处理的部分,Linux提出了其它的概念来处理,比如说软中断、tasklet和工作队列。
  2. 软中断 那软中断的工作原理又是什么呢?软中断是内核在编译阶段就预先定义好的,这是一个数组,数组元素个数正好是内核支持的软中断数量(Linux目前是32个,但实际只用了6个),而恰恰,内核为每个CPU都维护着一个表示软中断挂起标志位的32位变量,正好对应上面的数组元素个数。也就是说,哪个CPU将相应的bit位设置为1,这个CPU就需要处理这个软中断,至于软中断处理程序在预编译的时候已经写好了。这样的处理行为与硬中断完全一样,对于同一个软中断,每个CPU都有可能执行处理(所以,软中断要访问的数据结构必须使用自旋锁进行保护)。唯一不同的是,软中断的触发时机与硬中断不同:硬中断直接由硬件打断CPU的执行,调用相应的处理程序;而软中断的触发时机完全由内核设计者定义(也就是说,你可以让它任何时候触发)。但是,这样的机制也就固化了其处理行为,因为是预先定义好的。也就是说,用户无法根据自己的需要,设计自定义的软中断处理程序了。这怎么能行呢?于是,Linux在此基础上又提出了另一个概念,tasklet。
  3. tasklet Linux拿出其中的2个软中断,专门处理tasklet(一个高优先级,一个低优先级)。但是,tasklet的处理流程又大不一样。怎么不一样呢?就是哪个CPU激活的tasklet,一般就由哪个CPU执行,效率优先嘛。但是,不排除,在一个CPU上激活,在另一个CPU上执行的使用情况。但是,无论哪种情况,它们的执行都是与CPU绑定在一起的,也就是一一对应,也就是不存在并发访问同一个tasklet的时候。
  4. 工作队列 其实工作队列与tasklet的行为极其类似,只是软中断和tasklet都是在中断上下文中调用的,也就是不允许阻塞;而工作队列是运行在进程上下文中,也就是说,这是为内核线程处理延时任务提供的一种机制。故暂时不在本文的讨论范畴之内。
2.1 异常程序访问的数据结构

只有异常处理程序访问的数据结构,可能产生的竞态条件简单易懂,也很容易保护。最常见的异常处理程序就是系统调用,因为它可能被多个进程并发调用,从而为用户态的程序提供内核服务。所以说,异常处理程序访问的数据结构就是可以分配给一个或多个进程的一种资源。

避免这种资源可能产生的竞态条件,可以选择信号量,因为大部分情况下,想要访问这个资源的进程如果没有得到资源的使用权的话会选择休眠等待。而恰好,信号量就是这样的一种加锁机制。如果请求信号量失败,进程挂起,让出CPU的使用权给其它进程。这种情况下,自旋锁是不合适的,因为它是忙等待,一直占用CPU。值得一提的是,不论是单核系统还是多核系统,信号量都能工作的很好。

即使是开启内核抢占,也不会产生问题。如果持有信号量的进程被抢占,新进程会尝试申请信号量。但是,这时候申请信号量肯定失败,从而新进程进入休眠,等待旧进程释放信号量。

2.2 中断程序访问的数据结构

我们这儿要讨论的数据结构只是被中断程序的顶半部访问,不涉及底半部访问的数据结构,这类数据结构属于可延时函数访问的数据结构的范畴,后面再讨论。我们在学习中断的时候,已经知道,中断处理程序中的处理是串行化的,也就是说不会发生并发访问。所以,也就不需要同步。

但是,当数据结构被多个中断程序访问的时候,就会发生并发访问产生的竞态问题。尤其是在多核系统中,一个数据结构可能被多个不同的中断程序并发访问。这时候就需要同步了。

单核系统,竞态条件很好避免,只要关闭中断即可。其它同步技术也不合适。信号量阻塞进程,而中断万万不能被阻塞。另一方面,自旋锁会冻结系统:如果中断中正在访问的数据结构被中断,它不会释放锁;而新的中断程序一直在忙等待这个锁。其实就是发生了死锁。

多核系统处理更为复杂一些。因为中断都是局部中断,也就是每个CPU独享的。所以,只是简单的关闭中断无法有效避免竞态条件。因为,即使中断被禁止,其它CPU上的中断处理程序还会继续执行。所以,这时候需要关闭中断的同时,再申请一个自旋锁或者读写自旋锁保护数据结构。值得注意的是,这类自旋锁不会冻结系统。首先,因为关闭局部中断,所以同一CPU上的中断程序不会执行,也就不会发生上面所说的死锁。其次,因为是多核系统,中断程序发现锁被占用了,也不会阻止其它CPU上的中断程序释放这个锁。所以,无论哪种情况都不会发生死锁的情况。

为了方便处理多核系统中这种局部中断禁止和自旋锁结合在一起使用的情况,Linux提供了一些宏,如下表所示。单核系统中,这些宏只能禁止中断或者禁止内核抢占。

表5-9 与中断有关的自旋锁宏

描述

spin_lock_irq(l)

local_irq_disable();spin_lock(l)

unlock_irq(l)

spin_unlock(l);local_irq_enable()

spin_lock_bh(l)

local_bh_disable();spin_lock(l)

spin_unlock_bh(l)

spin_unlock(l);local_bh_enable()

spin_lock_irqsave(l,f)

local_irq_save(f);spin_lock(l)

spin_unlock_irqrestore(l,f)

spin_unlock(l);local_irq_restore(f)

read_lock_irq(l)

local_irq_disable( );read_lock(l)

read_unlock_irq(l)

read_unlock(l);local_irq_enable( )

read_lock_bh(l)

local_bh_disable( );read_lock(l)

read_unlock_bh(l)

read_unlock(l);local_bh_enable( )

write_lock_irq(l)

local_irq_disable();write_lock(l)

write_unlock_irq(l)

write_unlock(l);local_irq_enable( )

write_lock_bh(l)

local_bh_disable();write_lock(l)

write_unlock_bh(l)

write_unlock(l);local_bh_enable( )

read_lock_irqsave(l,f)

local_irq_save(f);read_lock(l)

read_unlock_irqrestore(l,f)

read_unlock(l);local_irq_restore(f)

write_lock_irqsave(l,f)

local_irq_save(f);write_lock(l)

write_unlock_irqrestore(l,f)

write_unlock(l);local_irq_restore(f)

read_seqbegin_irqsave(l,f)

local_irq_save(f);read_seqbegin(l)

read_seqretry_irqrestore(l,v,f)

read_seqretry(l,v);local_irq_restore(f)

write_seqlock_irqsave(l,f)

local_irq_save(f);write_seqlock(l)

write_sequnlock_irqrestore(l,f)

write_sequnlock(l);local_irq_restore(f)

write_seqlock_irq(l)

local_irq_disable();write_seqlock(l)

write_sequnlock_irq(l)

write_sequnlock(l);local_irq_enable()

write_seqlock_bh(l)

local_bh_disable();write_seqlock(l)

write_sequnlock_bh(l)

write_sequnlock(l);local_bh_enable()

2.3 可延时函数访问的数据结构

通过前面软中断、tasklet等概念的梳理,想必你对它们要访问的数据需要的保护方式有了一些初步的理解:采用哪种同步技术保护数据结构,完全取决于是属于哪类可延时函数。接下来,我们详细一一分析。

单核系统,通过上面的分析,不论是哪种机制访问数据结构,都不会产生竞态条件。因为它不会被其它可延时函数中断。也就无需使用同步了。

相反,多核系统就可能发生并发访问所带来的竞态问题。如下表所示,根据可延时函数的类型进行了列举:

延时函数类型

保护机制

软中断

自旋锁

一个tasklet

无需锁

多个tasklet

自旋锁

如前所述,软中断总是需要自旋锁进行保护,因为即使是同一个软中断也有可能被多个CPU并发访问。相反,一个tasklet不需要锁的保护,因为同一个tasklet不会发生并发访问。但是,如果数据被多个tasklet访问,就需要加锁保护了。

2.4 异常和中断同时访问的数据结构

如果数据结构既被异常处理程序(如系统调用)访问,又被中断处理程序访问,那该怎么保护数据呢?

对于这种情况,单核系统的处理非常简单,关闭中断即可。因为中断程序不可重入,也不能被异常处理程序中断。所以只要关闭中断,内核访问数据就不会被中断。

多核系统,我们就不得不考虑多个CPU的并发访问了。所以与中断访问数据一样,采用关闭中断与自旋锁相结合的方式。

但是,有时候使用信号量代替上面的自旋锁可能更好。尤其是异常处理程序等不到锁需要挂起的时候。举例来说,系统调用和中断同时访问某个数据:中断处理程序尝试申请信号量(调用down_trylock()),失败就不断尝试,还是相当于自旋锁的忙等待;另一方面,系统调用如果申请信号量失败,就挂起,让CPU执行其它操作,这完全符合系统调用时的预期行为。这种情况,信号量优于自旋锁,因为它让系统有一个更高的并发性能。

2.5 异常和可延时函数同时访问的数据结构

异常和可延时函数同时访问数据时,处理方式与异常和中断同时访问数据时类似。因为可延时函数本质上都是中断激活的,也是运行在中断上下文中的,在运行期间不会被异常中断。也就是说,使用关闭中断和自旋锁相结合的方式就足够了。

实际上,不用关闭硬中断即可,也就是调用local_bh_disable宏,只关闭可延时函数的执行。因为中断处理程序并没有访问数据,所以,只禁止可延时函数比禁止中断更有效率,因为中断可以继续被CPU响应。而在单个CPU上执行可延时函数是串行执行的,没有竞态条件产生。(这儿,禁止可延时函数指的是禁止再激活软中断,tasklet之类的,但是之前已经激活的还是要执行的。)

正如多数情况一样,多核系统中,自旋锁保证任何时候只有一个内核控制路径访问数据。

2.6 中断和可延时函数同时访问的数据结构

这种情况与中断和异常同时访问数据相似。单核系统,禁止中断即可。多核系统需要再加上自旋锁。

2.7 中断、异常和可延时函数同时访问的数据结构

与上一种情况一样,故不再累述。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式ARM和Linux 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux内核24-内核同步理解
我们可以把内核想象成一个服务器,专门响应各种请求。这些请求可以是CPU上正在运行的进程发起的请求,也可以是外部的设备发起的中断请求。所以说,内核并不是串行运行,而是交错执行。既然是交错执行,就会产生竞态条件,我们可以采用同步技术消除这种竞态条件。
Tupelo
2022/08/15
1.1K0
Linux内核33-信号量
对于信号量我们并不陌生。信号量在计算机科学中是一个很容易理解的概念。本质上,信号量就是一个简单的整数,对其进行的操作称为PV操作。进入某段临界代码段就会调用相关信号量的P操作;如果信号量的值大于0,该值会减1,进程继续执行。相反,如果信号量的值等于0,该进程就会等待,直到有其它程序释放该信号量。释放信号量的过程就称为V操作,通过增加信号量的值,唤醒正在等待的进程。
Tupelo
2022/08/15
1.6K0
Linux面试专题
Linux 的同步机制不断发展完善。从最初的原子操作,到后来的信号量,从大内核锁到今天的自旋锁。这些同步机制的发展伴随Linux从单处理器到对称多处理器的过渡;
老虎也淘气
2024/01/30
1400
Linux用户抢占和内核抢占详解(概念, 实现和触发时机)--Linux进程的管理与调度(二十)
多任务系统中, 内核负责管理各个任务, 或者说为每个任务分配CPU时间, 并且负责任务之间的通讯.
233333
2018/12/05
5.5K1
Linux用户抢占和内核抢占详解(概念, 实现和触发时机)--Linux进程的管理与调度(二十)
Linux内核36-内核同步之禁止中断
每一种技术的出现必然是因为某种需求。正因为人的本性是贪婪的,所以科技的创新才能日新月异。
Tupelo
2022/08/15
1.5K0
linux设备驱动第五篇:驱动中的并发与竟态
综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争。 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时、并行被执行。而并发的执行单元对共享资源(硬件资源和软件上的全局、静态变量)的访问则容易导致竞态(race conditions)。可能导致并发和竟态的情况有: SMP(Symmetric Multi-Processing),对称多处理结构。SMP是一种紧耦合、共享存储的系统模型,它的特点是多个CPU使用共同的系统总线
程序员互动联盟
2018/03/12
1.8K0
深度剖析Linux内核同步机制:实现高效可靠的并发编程
前言:非常早之前就接触过同步这个概念了,可是一直都非常模糊。没有深入地学习了解过,最近有时间了,就花时间研习了一下《linux内核标准教程》和《深入linux设备驱动程序内核机制》这两本书的相关章节。趁刚看完,就把相关的内容总结一下。
嵌入式Linux内核
2023/08/08
1K0
深度剖析Linux内核同步机制:实现高效可靠的并发编程
Linux内核同步原理学习笔记
在多年前,linux还没有支持对称多处理器SMP的时候,避免并发数据访问相对简单。
杨源鑫
2019/07/04
1.3K0
转:自旋锁(spinlock)
自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。
流柯
2018/08/31
8430
Linux内核22-软中断和tasklet
在之前的文章中,讲解中断处理相关的概念的时候,提到过有些任务不是紧急的,可以延后一段时间执行。因为中断服务例程都是顺序执行的,在响应一个中断的时候不应该被打断。相反,这些可延时任务执行时,可以使能中断。那么,将这些任务从中断处理程序中剥离出来,可以有效地保证内核对于中断响应时间尽可能短。这对于时间苛刻的应用来说,这是一个很重要的属性,尤其是那些要求中断请求必须在毫秒级别响应的应用。
Tupelo
2022/08/15
1.6K0
Linux内核21-Linux内核的中断处理过程
如前所述,我们知道异常的处理还是比较简单的,就是给相关的进程发送信号,而且不存在进程调度的问题,所以内核很快就处理完了异常。
Tupelo
2022/08/15
2.5K0
Linux内核21-Linux内核的中断处理过程
linux 内核同步机制使用
Linux 内核中的同步机制:原子操作、信号量、读写信号量、自旋锁的API、大内核锁、读写锁、大读者锁、RCU和顺序锁。 1、介绍 在现代操作系统里,同一时间可能有多个内核执行流在执行,即使单CPU内核也需要一些同步机制来同步不同执行单元对共享的数据的访问。 主流的Linux内核中的同步机制包括: 原子操作 信号量(semaphore) 读写信号量(rw_semaphore) 自旋锁spinlock 大内核锁BKL(Big Kernel Lock) 读写锁rwlock、 brlock(只包含在2.4内核中
李海彬
2018/03/22
2.4K0
Linux调度系统全景指南(上篇)
| 导语 本文主要是讲Linux的调度系统, 由于全部内容太多,分三部分来讲,调度可以说是操作系统的灵魂,为了让CPU资源利用最大化,Linux设计了一套非常精细的调度系统,对大多数场景都进行了很多优化,系统扩展性强,我们可以根据业务模型和业务场景的特点,有针对性的去进行性能优化,在保证客户网络带宽前提下,隔离客户互相之间的干扰影响,提高CPU利用率,降低单位运算成本,提高市场竞争力。欢迎大家相互交流学习!
刘盼
2021/03/10
1.6K0
Linux调度系统全景指南(上篇)
多线程编程之自旋锁
  自旋锁是专为防止多处理器并发(实现保护共享资源)而引入的一种锁机制。自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,“自旋”一词就是因此而得名。自旋锁在内核中大量应用于中断处理等部分(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,即在标志寄存器中关闭/打开中断标志位,不需要自旋锁)。
物流IT圈
2019/07/16
1.2K0
Linux设备驱动程序(五)——并发和竞态
并发相关的缺陷是最容易制造的,也是最难找到的,为了响应现代硬件和应用程序的需求,Linux 内核已经发展到同时处理更多事情的时代。这种变革使得内核性能及伸缩性得到了相当大的提高,然而也极大提高了内核编程的复杂性。
Gnep@97
2023/08/10
4650
Linux设备驱动程序(五)——并发和竞态
实时Linux内核的实现
实时系统要求对事件的响应时间不能超过规定的期限,响应时间是指从某个事件发生到负责处理这个事件的进程处理完成的时间间隔,最大响应时间应该是确定的、可以预测的。
用户7244416
2021/10/28
6.8K0
实时Linux内核的实现
面试官让你讲讲Linux内核的竞争与并发,你该如何回答?
  在早期的 Linux内核中,并发的来源相对较少。早期内核不支持对称多处理( symmetric multi processing,SMP),因此,导致并发执行的唯一原因是对硬件中断的服务。这种情况处理起来较为简单,但并不适用于为获得更好的性能而使用更多处理器且强调快速响应事件的系统。
嵌入式与Linux那些事
2021/05/20
7850
linux驱动最新面试题(面试题整理,含答案)
转载请标明原址:linux驱动最新面试题(面试题整理,含答案)_不忘初心-CSDN博客_linux驱动面试题
全栈程序员站长
2022/08/31
3.9K0
Linux kernel 同步机制(下篇)
在上一部分,我们讨论了最基本常见的几类同步机制,这一部分我们将讨论相对复杂的几种同步机制,尤其是读写信号量和RCU,在操作系统内核中有相当广泛的应用。
Linux阅码场
2020/09/10
2.3K0
Linux kernel 同步机制(下篇)
Linux 同步管理
对于基础类型操作,使用原子变量就可以做到线程安全,那原子操作是如何保证线程安全的呢?linux中的原子变量如下:
一只小虾米
2023/03/20
1.7K0
Linux 同步管理
相关推荐
Linux内核24-内核同步理解
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文