Linux内核原子操作(1)基本原理

概述

原子(atomic)本意是“不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为“不可被中断的一个或一系列操作”,可以保证指令以原子的方式运行,即执行过程不被打断,如果被中断则可能会引起执行结果和预期不符。

竟态问题

原子操作的提出主要是为了解决程序运行过程中的竞态问题,以程序中一个共享全局变量的自加操作count++为例,处理器完成这样一个操作需要三个步骤:

  1. 从内存中读取count变量的值到寄存器中;
  2. 将寄存器中的值加1;
  3. 将寄存器中的值写回到内存中。

这个操作也称为RMW(Read-Modify-Write)。现在假设存在两个执行线程同时在对count(count初始值假设为0)执行自加操作,预期的结果应当是两个线程串行地完成了count的自增操作,count最终的值为2;但在并发场景下,处理器的实际执行序列却可能会是下面这个情况:
在这里插入图片描述
之所以会产生上面的情况,原因就是RMW操作本身不具备原子性,它可能会被中断打断或者被并行程序产生的数据竞争影响。为了解决这种问题,就需要让RMW操作成为一个原子操作,这需要硬件提供机制来保证。

单处理器系统下的原子操作

在单处理器(Uni-Processor)系统中,处理器的执行流程只会受到中断机制的影响,由于中断只能发生于指令之间,因此能够在单条指令中完成的操作都可以认为是“原子操作”。单处理器系统实现原子操作的方式有两种:

  • 提供能完成多步操作的单条指令:这在采用复杂指令集架构的处理器上比较常见,例如x86架构提供的inc指令就可以通过一条指令完成变量的自加操作;
  • 关中断:处理器中断关闭后,就可以不间断地执行一系列指令,等所有操作完成后再打开中断。

多处理器系统下的原子操作

在多处理器(Multi-Processor)系统中,面临的并发问题要严峻很多,由于系统中有多个处理器在独立地运行,即使是一条指令执行期间也会受到其它处理器的干扰,导致指令执行结果错误。在不同的处理器体系结构下,硬件提供的原子操作实现机制会存在区别,但通常情况下,都会保证多处理器下进行零次或一次对齐内存访问的指令是具备原子性的。这里,我们以x86和ARM架构为例说明它们提供的原子机制。

x86架构下的原子操作

在x86架构下,处理器提供了在指令执行期间对总线加锁的手段。通过在需要原子操作的指令前附加lock指令前缀将总线锁定,保证了指令执行时不会受到其它处理器的影响。
在这里插入图片描述
当某条指令被加上lock指令前缀时,该指令在执行前,会把处理器的#HLOCK引脚拉低,该引脚被拉低导致总线被锁,其他处理器不能访问总线,直到指令执行完毕,处理器的#HLOCK引脚恢复以后,总线的访问权才被释放。x86架构只有指定的几个指令才可以附加lock指令前缀。操作系统把这些附加了lock指令前缀的指令包装后,做成多种原子操作API供应用使用。

ARM架构下的原子操作

ARM架构下的原子操作不使用总线锁定的方式,而是采用独占访问机制。ARM提供了一对独占内存加载和存储的指令,用于支持原子操作实现:

  • ldxr指令:内存独占加载指令。从内存中以独占的方式加载内存地址的值到通用寄存器里;
  • stxr指令:内存独占存储指令。以独占的方式把新的数据存储到内存中。

ldxr是内存加载指令的一种,不过它会通过独占监控器(exclusive monitor)来监控器这个内存的访问,独占监控器会把这个内存地址标记为独占访问模式,保证以独占的方式来访问这个内存地址,不受其他因素的影响。而stxr是有条件的存储指令,它会把新数据写入ldxr指令标记独占访问的内存地址里。
在这里插入图片描述
ARM结构提供了两种类型的独占监视器:

  • 本地监视器(Local Monitor): 每一个处理器内部包含一个本地监视器,标记了本地处理器对某块内存的独占访问;
  • 全局监视器(Global Monitor):全局唯一,标记了系统中每个处理器对某块内存的独占访问。

独占监控器一共有两种状态: 开放访问状态和独占访问状态。

独占访问机制

当CPU通过ldxr指令从内存加载数据时,CPU会把这个内存地址标记为独占访问,然后CPU内部的独占监控器的状态变成了独占访问状态。当CPU执行stxr指令的时候,需要根据独占监控器的状态来做决定:

  • 如果独占监控器的状态为独占访问状态,并且stxr指令要存储的地址正好是刚才使用ldxr指令标记过的,那么stxr指令存储成功,stxr指令返回0,独占监控器的状态变成了开放访问状态;
  • 如果独占监控器的状态为开发访问状态,那么stxr指令存储失败,stxr指令返回1,独占监控器的状态不变,依然保持开发访问状态。
    在这里插入图片描述

相关参考

  • 《Intel处理器手册》
  • 《Linux内核设计与实现》
  • 《奔跑吧,Linux内核》
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值