原子操作提供了指令原子执行,中间没有中断。就像原子被认为是不可分割颗粒一样,原子操作(atomic operation)是不可分割的操作。

如下面简单的例子:

Thread 1                  Thread 2
---------------------------------------------
get i (7)                 get i (7)

increment i (7->8)

---                      increment i (7->8)

write back i (8)          ----

---                          write back i (8)

如果有原子操作的话,那么这种竞争就不会发生,也不可能发生,结果只能是下面的一种:

Thread 1                            Thread 2
--------------------------------------------------------
get, increment, and store i(7->8)        ---

---                                 get, increment, and store i(8->9)

或者

Thread 1                            Thread 2
--------------------------------------------------------
---                                  get, increment, and store i(7->8)        
get, increment, and store i(8->9)          ---

在linux下,原子整数操作方法是一个特殊的类型,atomic_t,原型定义如下:

typedef struct{

    volatile int counter;

} atomic_t;

对于声明为volatile的好处,可以参考【百度百科-volatile】:http://baike.baidu.com/view/608706.htm?fr=aladdin

定义一种这样的类型有两种好处:1、让那些原子操作函数只接受atomic_t的数据类型作为参数,同样的也确保了这种数据类型不会传到其他的非原子操作函数;2、通过使用atomic_t这种数据类型是gcc编译器不会对这种类型的值的存取进行优化,因为对于原子操作收到正确的内存地址是非常重要的,确保不是别名。

在linux内核源码中对于原子操作的数据类型和方法描述文件为arch/x86/include/asm/atomic.h(注:这是对于内核为2.6.39以及处理器为x86的,其他的可能在不同的目录下)。一些体系结构提供了独特的原子操作方法。

下面介绍几种原子操作方法:

/**
 * atomic_add - add integer to atomic variable
 * @i: integer value to add
 * @v: pointer of type atomic_t
 *
 * Atomically adds @i to @v.
 */
static inline void atomic_add(int i, atomic_t *v)
{
    asm volatile(LOCK_PREFIX "addl %1,%0"
             : "+m" (v->counter)
             : "ir" (i));
}
上面的是对于原子加操作。采用的方式是先对内存进行加锁,是其他的CPU不能存取内存。

关于内联汇编的方式【基本知识】:http://www.cppblog.com/jb8164/archive/2008/02/26/43260.html;

如果想要内联汇编【深入理解】:http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html;

/**
 * atomic_sub - subtract integer from atomic variable
 * @i: integer value to subtract
 * @v: pointer of type atomic_t
 *
 * Atomically subtracts @i from @v.
 */
static inline void atomic_sub(int i, atomic_t *v)
{
    asm volatile(LOCK_PREFIX "subl %1,%0"
             : "+m" (v->counter)
             : "ir" (i));
}

进行的原子减操作采用的是类似的方式;也是先对内存加锁,然后再操作。

/**
 * atomic_read - read atomic variable
 * @v: pointer of type atomic_t
 *
 * Atomically reads the value of @v.
 */
static inline int atomic_read(const atomic_t *v)
{
    return (*(volatile int *)&(v)->counter);
}

这个是对于原子的读操作。为了防止编译器对数值进行优化而采用的是寄存器中的数值,需要将其转换为volatile类型的数据,使之每次都从内存中读取,对于每次读取操作不会发生读到一半的情况,每次读操作要么才写操作之前,要么在写操作之后。

其他的原子操作采用的是类似的方式。

linux中原子操作实现方式的更多相关文章

  1. 全新linux中通过编译方式安装nginx

    先去官网下载linux.tar.gz包 http://nginx.org/en/download.html   传到linxu中 解压tar包 在软件包nginx-1.15.9目录下对NGINX进行配 ...

  2. linux中软件安装方式

    通常Linux应用软件的安装包有三种: tar包,如software-1.2.3-1.tar.gz.它是使用UNIX系统的打包工具tar打包的. rpm包,如software-1.2.3-1.i386 ...

  3. linux中切换用户方式su和su -的区别

    Using su The  su  command allows users to open a terminal window, and from that terminal start a sub ...

  4. linux系统原子操作

    一.概念 原子操作提供了指令原子执行,中间没有中断.就像原子被认为是不可分割颗粒一样,原子操作(atomic operation)是不可分割的操作.      c语言中一个变量的自加1操作,看起来很简 ...

  5. Linux中同步互斥机制研究之原子操作

    操作系统中,对共享资源的访问需要有同步互斥机制来保证其逻辑的正确性,而这一切的基础便是原子操作. | 原子操作(Atomic Operations):    原子操作从定义上理解,应当是类似原子的,不 ...

  6. Linux中架构中的备份服务器搭建(rsync)

    本期内容概要 Linux中的备份方式 架构中备份服务器搭建(rsync) 内容详细 1.备份方式 1. cp : 本机复制(只能作用在本机) 2. scp : 远程复制 两种模式: 推 : 本地上传到 ...

  7. linux中mysql密码找回的两种方式

    方法一:修改my.cnf配置文件 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的  ...

  8. Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式

    Linux就这个范儿 第15章 七种武器  linux 同步IO: sync.fsync与fdatasync   Linux中的内存大页面huge page/large page  David Cut ...

  9. Linux中删除特殊名称文件的多种方式

    今日分享:我们在肉体的疾病方面花了不少钱,精神的病害方面却没有花什么,现在已经到了时候,我们应该有不平凡的学校.--<瓦尔登湖> 前言 我们都知道,在linux删除一个文件可以使用rm命令 ...

随机推荐

  1. 【mpvue】使用Mpvue撸一个简单的小程序

    一.快速创建一个mpvue项目   全局安装 vue-cli   (如果有就不需要装了) 创建一个基于mpvue-quickstart模板的新项目,记得选择安装vuex vue init mpvue/ ...

  2. autocad.net-图片打印合成

    调用打印程序“PublishToWeb JPG.pc3”进行图片打印,该打印驱动程序中内置了很多的打印方案,在同尺寸的打印方案下,数据范围越大打印出来的清晰度就越差,内置的尺寸不一定都满足,在又要通过 ...

  3. Android--监听View的两个指头是放大和缩小

    private double nLenStart = 0;//监听 WebView所用手势 @Override public boolean onTouch(View v, MotionEvent e ...

  4. 【Redis】Redis学习(七) Redis 持久化之RDB和AOF

    Redis 持久化提供了多种不同级别的持久化方式:一种是RDB,另一种是AOF. RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot). AOF ...

  5. [Android] 图片裁剪总结——自定义裁剪工具

    上次弄完调用系统裁剪之后,我又试着做一个自定义的裁剪工具. 原文地址请保留http://www.cnblogs.com/rossoneri/p/3988405.html 老习惯,文章开始前还是先把我参 ...

  6. 【python】python常用函数

    urlencode与urldecode 当url中包含中文或者参数包含中文,需要对中文或者特殊字符(/.&)做编码转换. urlencode的本质:把字符串转为gbk编码,再把\x替换成%.如 ...

  7. Azure 虚拟机诊断设置问题排查

    Azure 为用户提供了可以自己配置的性能监控功能:Azure 诊断扩展.但是在具体配置中,经常会遇到各种各样的问题.不了解监控的工作机制常常给排查带来一定难度.这里我们整理了关于 Azure 虚拟机 ...

  8. LabVIEW TCP/IP 断开重连问题

    LabVIEW的TCP/IP函数库非常好用,但是不恰当地设置打开连接结点的参数将带来一些问题,麻烦.如下图的打开连接的参数设置: 上图中指定了本地的端口,会发生这样的情况.当我们关闭应用程序之后,连接 ...

  9. Android5.0中Material Design的新特性

    最近项目中需要用到Material Design,整理了下面几个常用的控件,以便记忆. 一.Snackbar 1.作用:与Toast类似,但是可以点击监听: 2.使用: (1)Snackbar调用静态 ...

  10. git pull与本地修改冲突

    1.先将本地修改存储起来 $ git stash 这样本地的所有修改就都被暂时存储起来 . $ git stash list                 可以看到保存的信息: git stash暂 ...