学习笔记——操作系统_Linux原子操作
2013-01-28 22:30
369 查看
这篇摘录有关原子操作的说明,参考了以下的文章,并添加我的说明
http://blog.csdn.net/vividonly/article/details/6599502(针对原子操作解释的很全面) http://baike.baidu.com/view/809659.htm http://blog.csdn.net/sunupzhou/article/details/7537779 http://blog.sina.com.cn/s/blog_6472c4cc0100qxcd.html(这个哥们的技术很全面)
所谓原子操作,就是“不可中断的一个或一系列操作”。
硬件级的原子操作:在单处理器系统(UniProcessor)中,能够在单条指令中完成的操作都可以认为是“原子操作”,因为中断只发生在指令边缘。
【说明】这个单条指令中完成的操作,因为中断只能在指令边缘,可以这么理解:中断发生时,流水线会把当前中断之前的指令执行完,直至修改处理器状态,而中断发生之后的指令排空,并且中断之后的指令不能修改处理器状态,所以指令的状态修改都是在指令提交阶段完成。
在多处理器结构中(Symmetric Multi-Processor)就不同了,由于系统中有多个处理器独立运行,即使能在单条指令中完成的操作也有可能受到干扰。在X86平台生,CPU提供了在指令执行期间对总线加锁的手段。CPU上有一根引线#HLOCK
pin连到北桥,如果汇编语言的程序中在一条指令前面加上前缀"LOCK",经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。
【说明】在多处理器系统中,由于基于cache一致性协议原则,当系统修改内存中的某个值时,会告知其他所有当前cache该值的CPU;这儿也隐含说明:所谓的原子操作,是针对内存的操作,而不是针对寄存器的操作,这个时候要写穿透。
问题:我们已经通过cache一致性协议确保数据正确了,为什么还要通过上述机制进行原子操作呢?
分析cache一致性协议,主要是当前常用的基于目录的cache一致性协议:
cache中数据的状态包括:
共享:一个或者多个处理器拥有cache的数据块
未缓存:没有任何一个处理器含有该数据块
修改:只有一个处理器拥有该cache块的副本并已经进行写操作
当在SMP中某个处理器修改了内存中的值之后,即cache数据状态变为修改,这个时候要传递到其他的处理器中,这个时候通过目录协议,是通过目录控制器有选择的发送数据获取和无效操作来完成的。任何cache块要执行写操作时都必须处于独占的状态,而且共享数据在存储器中的副本必须被替换。
在这个时候,当处理器A写数据后,系统应该通过目录控制器将处理器B中的值设定为无效。这个时候为什么还要额外处理呢?
软件层面的原子操作:
原子操作通常针对int或bit类型的数据,但是Linux并不能直接对int进行原子操作,而只能通过atomic_t的数据结构来进行。目前了解到的原因有两个。一是在老的Linux版本,atomic_t实际只有24位长,低8位用来做锁。这是由于Linux是一个跨平台的实现,可以运行在多种
CPU上,有些类型的CPU比如SPARC并没有原生的atomic指令支持,所以只能在32位int使用8位来做同步锁,避免多个线程同时访问。(最新版SPARC实现已经突破此限制)。原子整数操作最常见的用途就是实现计数器。常见的用法是:
系统中具体的实现方式就不管了。
为什么关注原子操作?
1)在确认一个操作是原子的情况下,多线程环境里面,我们可以避免仅仅为保护这个操作在外围加上性能开销昂贵的锁。
2)借助于原子操作,我们可以实现互斥锁。
3)借助于互斥锁,我们可以把一些列操作变为原子操作。
http://blog.csdn.net/vividonly/article/details/6599502(针对原子操作解释的很全面) http://baike.baidu.com/view/809659.htm http://blog.csdn.net/sunupzhou/article/details/7537779 http://blog.sina.com.cn/s/blog_6472c4cc0100qxcd.html(这个哥们的技术很全面)
所谓原子操作,就是“不可中断的一个或一系列操作”。
硬件级的原子操作:在单处理器系统(UniProcessor)中,能够在单条指令中完成的操作都可以认为是“原子操作”,因为中断只发生在指令边缘。
【说明】这个单条指令中完成的操作,因为中断只能在指令边缘,可以这么理解:中断发生时,流水线会把当前中断之前的指令执行完,直至修改处理器状态,而中断发生之后的指令排空,并且中断之后的指令不能修改处理器状态,所以指令的状态修改都是在指令提交阶段完成。
在多处理器结构中(Symmetric Multi-Processor)就不同了,由于系统中有多个处理器独立运行,即使能在单条指令中完成的操作也有可能受到干扰。在X86平台生,CPU提供了在指令执行期间对总线加锁的手段。CPU上有一根引线#HLOCK
pin连到北桥,如果汇编语言的程序中在一条指令前面加上前缀"LOCK",经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。
【说明】在多处理器系统中,由于基于cache一致性协议原则,当系统修改内存中的某个值时,会告知其他所有当前cache该值的CPU;这儿也隐含说明:所谓的原子操作,是针对内存的操作,而不是针对寄存器的操作,这个时候要写穿透。
问题:我们已经通过cache一致性协议确保数据正确了,为什么还要通过上述机制进行原子操作呢?
分析cache一致性协议,主要是当前常用的基于目录的cache一致性协议:
cache中数据的状态包括:
共享:一个或者多个处理器拥有cache的数据块
未缓存:没有任何一个处理器含有该数据块
修改:只有一个处理器拥有该cache块的副本并已经进行写操作
当在SMP中某个处理器修改了内存中的值之后,即cache数据状态变为修改,这个时候要传递到其他的处理器中,这个时候通过目录协议,是通过目录控制器有选择的发送数据获取和无效操作来完成的。任何cache块要执行写操作时都必须处于独占的状态,而且共享数据在存储器中的副本必须被替换。
在这个时候,当处理器A写数据后,系统应该通过目录控制器将处理器B中的值设定为无效。这个时候为什么还要额外处理呢?
软件层面的原子操作:
原子操作通常针对int或bit类型的数据,但是Linux并不能直接对int进行原子操作,而只能通过atomic_t的数据结构来进行。目前了解到的原因有两个。一是在老的Linux版本,atomic_t实际只有24位长,低8位用来做锁。这是由于Linux是一个跨平台的实现,可以运行在多种
CPU上,有些类型的CPU比如SPARC并没有原生的atomic指令支持,所以只能在32位int使用8位来做同步锁,避免多个线程同时访问。(最新版SPARC实现已经突破此限制)。原子整数操作最常见的用途就是实现计数器。常见的用法是:
atomic_t use_cnt; atomic_set(&use_cnt, 2); atomic_add(4, &use_cnt); atomic_inc(use_cnt);
系统中具体的实现方式就不管了。
为什么关注原子操作?
1)在确认一个操作是原子的情况下,多线程环境里面,我们可以避免仅仅为保护这个操作在外围加上性能开销昂贵的锁。
2)借助于原子操作,我们可以实现互斥锁。
3)借助于互斥锁,我们可以把一些列操作变为原子操作。
相关文章推荐
- linux学习笔记4--原子操作
- 操作系统学习笔记(20)--开中断、关中断及原子操作
- [Linux学习笔记]第1天:操作系统的发展史,linux诞生,Linux发行商,shell,terminal,shell使用技巧,文件目录,基本操作
- 个人学习笔记---linux原子操作的实现原理
- Android深度探索:HAL与驱动开发学习笔记--并发控制之原子操作
- linux系统管理学习笔记之七---linux文件系统的操作
- 七月二十七日 Linux操作系统c语言学习笔记
- linux内存操作--ioremap和mmap学习笔记
- linux学习笔记一----------文件相关操作
- 实验楼Linux学习笔记(六)之文件系统操作与磁盘管理
- linux内核分析学习笔记:操作系统的进程切换
- Linux学习笔记之 2 Linux系统的基本操作
- linux学习笔记(二)文件操作命令
- Linux学习笔记_04(vi、vim基本操作)
- linux学习笔记一——sudo:无法切换为sudoers组ID:不允许的操作
- linux基础学习笔记——操作
- Linux学习笔记 - 第二章 Linux操作系统
- linux & C++Primer 学习笔记--fstream 非常好用的文件操作流
- Linux 学习笔记4 之 装fedora, 装五笔输入法,及设置默认操作系统
- IPython(jupyter)简单介绍和基本交互操作 - 千月的python linux 系统管理指南学习笔记(5)