linux中原子操作实现方式
原子操作提供了指令原子执行,中间没有中断。就像原子被认为是不可分割颗粒一样,原子操作(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中原子操作实现方式的更多相关文章
- 全新linux中通过编译方式安装nginx
先去官网下载linux.tar.gz包 http://nginx.org/en/download.html 传到linxu中 解压tar包 在软件包nginx-1.15.9目录下对NGINX进行配 ...
- linux中软件安装方式
通常Linux应用软件的安装包有三种: tar包,如software-1.2.3-1.tar.gz.它是使用UNIX系统的打包工具tar打包的. rpm包,如software-1.2.3-1.i386 ...
- linux中切换用户方式su和su -的区别
Using su The su command allows users to open a terminal window, and from that terminal start a sub ...
- linux系统原子操作
一.概念 原子操作提供了指令原子执行,中间没有中断.就像原子被认为是不可分割颗粒一样,原子操作(atomic operation)是不可分割的操作. c语言中一个变量的自加1操作,看起来很简 ...
- Linux中同步互斥机制研究之原子操作
操作系统中,对共享资源的访问需要有同步互斥机制来保证其逻辑的正确性,而这一切的基础便是原子操作. | 原子操作(Atomic Operations): 原子操作从定义上理解,应当是类似原子的,不 ...
- Linux中架构中的备份服务器搭建(rsync)
本期内容概要 Linux中的备份方式 架构中备份服务器搭建(rsync) 内容详细 1.备份方式 1. cp : 本机复制(只能作用在本机) 2. scp : 远程复制 两种模式: 推 : 本地上传到 ...
- linux中mysql密码找回的两种方式
方法一:修改my.cnf配置文件 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 ...
- 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 ...
- Linux中删除特殊名称文件的多种方式
今日分享:我们在肉体的疾病方面花了不少钱,精神的病害方面却没有花什么,现在已经到了时候,我们应该有不平凡的学校.--<瓦尔登湖> 前言 我们都知道,在linux删除一个文件可以使用rm命令 ...
随机推荐
- js-ES6学习笔记-Promise对象(2)
1.Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的.它的作用是为Promise实例添加状态改变时的回调函数. 2.Promise.pr ...
- eclipse java web项目经常自动调试进入debug模式
今天在运行Javaweb项目时,程序运行运行着就自动调试进入ThreadpoolExecutor,看着非常影响心情.最后在网上搜解决方法最后找到原因,解决方法如下. Window——>Prefe ...
- 【js实例】Array类型的9个数组方法,Date类型的41个日期方法,Function类型
前文提要:[js实例]js中的5种基本数据类型和9种操作符 Array类型的9个数组方法 Array中有9个数组方法: 1.检测数组 2.转换方法 3.栈方法 4.队列方法 5.冲排序方法6.操作方法 ...
- AngularJS图片上传功能实践
逻辑理清楚了:service提供FileReader函数,directive提供点击事件的绑定和监听,controller用来修改html上的ng-src属性值 1.HTML <input ty ...
- mac下的tcp抓包
所需工具: 1.所需工具wireshark软件 操作步骤: 1.打开wireshark添加手机端口监测. 在控制台中输入命令:rvictl -s iPhoneDeviceId 添加成功之后,wires ...
- Android 如何执行java命令
android的程序基于java开发,当我们接上调试器,执行adb shell,就可以执行linux命令,但是却并不能执行java命令. 那么在android的shell中是否就不能执行java程序了 ...
- [Android] (在ScrollView里嵌套view)重叠view里面的onTouchEvent的调用方法
在我前面的自定义裁剪窗口的代码中,我把裁剪的view放在了大的scrollview里,这样就出现了程序只能触发scrollview,无法操作我的裁剪窗口.所以我加了那篇博客下面最后两段代码.其实我遇到 ...
- qt调用js,js调用qt
<html> <script language="JavaScript"> function qtcalljs() { alert("sdfsd& ...
- Eclipse+Weblogic 12开发简单的Enterprise Application
学到EJB方面的内容,遇到了很多问题,翻阅了无数遍Java EE和Weblogic的官方文档,在google上进行了无数次搜索都没有答案,可能我要找的答案太冷门.这一切都起源于Java EE官方文档里 ...
- python图像处理:pytesseract和PIL
大概介绍下相关模块的概念: Python-tesseract 是光学字符识别Tesseract OCR引擎的Python封装类.能够读取任何常规的图片文件(JPG, GIF ,PNG , TIFF等) ...