Linux内核29-原子操作

简介: Linux内核29-原子操作

1 引言


汇编指令读写内存变量的过程我们称为read-modify-write,简称为RMW操作。也就是说,它们读写一个内存区域两次,第一次读取旧值,第二次写入新值。

假设有两个不同的内核控制路径运行在两个CPU上,同时尝试RMW操作相同的内存区域且执行的是非原子操作。起初,两个CPU尝试读取相同位置,但是内存仲裁器(促使串行访问RAM的电路)确定一个可以访问,让另一个等待。但是,当第一个读操作完成,延时的CPU也会读取相同的旧值。但是等到两个CPU都往这个内存区域写入新值的时候,还是由内存仲裁器决定谁先访问,然后写操作都会成功。但是,最终的结果却是最后写入的值,先写入的值会被覆盖掉。

防止RMW操作造成的竞态条件最简单的方式就是保证这样的指令操作是原子的,也就是这个指令的执行过程不能被打断。这就是原子操作的由来。


2 X86体系架构


2.1 X86原子指令

让我们看一下X86的汇编指令有哪些是原子的:

  • 进行零或一对齐内存访问的汇编指令是原子的。
  • RMW操作汇编指令(比如incdec),如果在read之后,write之前内存总线没有被其它CPU抢占,那么这些指令就是原子的。
  • 所以,基于上一点,RMW操作汇编指令前缀lock(0xf0)就称为原子操作指令。当控制单元检测到这个前缀,它会锁住内存总线,直到指令完成。
  • 带有前缀rep(0xf2、0xf3,强迫控制单元重复指令多次)的汇编指令就不是原子的。

通过上面的描述可知,X86体系架构本身有一些指令就是原子指令。对于RMW操作指令(比如incdec),本身不是原子指令,但是可以通过在指令前面,使用前缀lock指令锁住内存总线,阻止在写内存时,其它CPU抢占,从而实现原子操作。


2.2 ARM原子指令


但是,ARM体系架构中不存在lock指令,所以它在原子指令的实现上是不一样的。ARMv6之前的版本,因为不支持多核,所以只要关闭中断即可;而ARMv6及以后的版本,支持多核系统,只关闭中断是不可以实现原子指令的。于是,该版本引入了新的独占指令ldrexstrex,通过这两个指令实现原子操作。比如,下面以原子加法为例,代码如下:

static inline void atomic_add(int i, atomic_t *v)
{
    unsigned long tmp;
    int result;
    __asm__ __volatile__("@ atomic_add\n"
    "1: ldrex %0, [%3]\n"       // ---------- (0)
    " add %0, %0, %4\n"         // ---------- (1)
    " strex %1, %0, [%3]\n"     // ---------- (2)
    " teq %1, #0\n"             // ---------- (3)
    " bne 1b"                   // ---------- (4)
    : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
    : "r" (&v->counter), "Ir" (i)
    : "cc");
}

代码解析:

  • (0)从v->counter地址处取出其值,将其存入result;
  • (1)计算result=result+i;
  • (2)将result的结果存入v->counter地址处,这一步操作是否成功的结果写入到tmp临时变量中;
  • (3)判断tmp是否等于0;
  • (4)第(3)结果如果等于0,则成功;如果不等于0,则跳转到标签1处继续执行,直到成功。

所以说,X86这种锁内存总线的方式简单好用,但是毕竟牺牲了性能;而ARM这种独占指令则更为高效,只不过实现上更为复杂一点。


3 Linux原子操作


但是,我们在编写完C代码后,编译器不能保证给你使用原子指令进行替代。因此,Linux内核提供了atomic_t类型变量并提供了相关的操作函数和宏(如表5-4所示)。

表5-4 Linux中的原子操作

函数 描述
atomic_read(v) 返回*v
atomic_set(v,i) *v=i
atomic_add(i,v) *v+i
atomic_sub(i,v) *v-i
atomic_sub_and_test(i, v) 如果*v-i = 0
返回1;否则0
atomic_inc(v) *v+1
atomic_dec(v) *v-1
atomic_dec_and_test(v) 如果*v-1 = 0
返回1;否则0
atomic_inc_and_test(v) 如果*v+1 = 0
返回1;否则0
atomic_add_negative(i, v) 如果*v+i < 0
返回1;否则0
atomic_inc_return(v) 返回*v-1
atomic_dec_return(v) 返回*v+i
atomic_add_return(i, v) 返回*v-i


相关文章
|
2月前
|
监控 Linux 开发者
理解Linux操作系统内核中物理设备驱动(phy driver)的功能。
综合来看,物理设备驱动在Linux系统中的作用是至关重要的,它通过与硬件设备的紧密配合,为上层应用提供稳定可靠的通信基础设施。开发一款优秀的物理设备驱动需要开发者具备深厚的硬件知识、熟练的编程技能以及对Linux内核架构的深入理解,以确保驱动程序能在不同的硬件平台和网络条件下都能提供最优的性能。
101 0
|
5月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
224 67
|
3月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
90 0
|
5月前
|
存储 Linux
Linux内核中的current机制解析
总的来说,current机制是Linux内核中进程管理的基础,它通过获取当前进程的task_struct结构的地址,可以方便地获取和修改进程的信息。这个机制在内核中的使用非常广泛,对于理解Linux内核的工作原理有着重要的意义。
199 11
|
6月前
|
自然语言处理 监控 Linux
Linux 内核源码分析---proc 文件系统
`proc`文件系统是Linux内核中一个灵活而强大的工具,提供了一个与内核数据结构交互的接口。通过本文的分析,我们深入探讨了 `proc`文件系统的实现原理,包括其初始化、文件的创建与操作、动态内容生成等方面。通过对这些内容的理解,开发者可以更好地利用 `proc`文件系统来监控和调试内核,同时也为系统管理提供了便利的工具。
239 16
|
8月前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
424 15
|
8月前
|
安全 Linux 测试技术
Intel Linux 内核测试套件-LKVS介绍 | 龙蜥大讲堂104期
《Intel Linux内核测试套件-LKVS介绍》(龙蜥大讲堂104期)主要介绍了LKVS的定义、使用方法、测试范围、典型案例及其优势。LKVS是轻量级、低耦合且高代码覆盖率的测试工具,涵盖20多个硬件和内核属性,已开源并集成到多个社区CICD系统中。课程详细讲解了如何使用LKVS进行CPU、电源管理和安全特性(如TDX、CET)的测试,并展示了其在实际应用中的价值。
189 4
|
9月前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
9月前
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####
|
9月前
|
存储 缓存 网络协议
Linux操作系统的内核优化与性能调优####
本文深入探讨了Linux操作系统内核的优化策略与性能调优方法,旨在为系统管理员和高级用户提供一套实用的指南。通过分析内核参数调整、文件系统选择、内存管理及网络配置等关键方面,本文揭示了如何有效提升Linux系统的稳定性和运行效率。不同于常规摘要仅概述内容的做法,本摘要直接指出文章的核心价值——提供具体可行的优化措施,助力读者实现系统性能的飞跃。 ####