什么是原子操作:
原子操作是为了确保对一个整型数据的更改具有排他性。原子操作就是要么不执行,一旦执行就会执行完成,是不可被打断的一个,或一系列的动作,即在完成任务前不会被其他事件所打断,就像原子不可被分割成颗粒一样。单处理中,可以用单条指令完成的指令可以被看成是一个原子操作。软件中的原子操作依赖于硬件原子操作的支持。当然原子操作,也可以当引用计数使用。
其实本质上原子操作和锁实现同样的功能,都是为了保护共享对象,它具有原子性,和顺序性。原子性确保指令执行期间不被打断,要么全部执行,要么根本不执行。而顺序性确保即使两条或多条指令出现在独立的执行线程中,甚至独立的处理器上,它们本该执行的顺序依然要保持。
原子操作会被打断,但不会影响结果:
在执行原子操作的过程中,它可能会被其它执行流打断,比如中断、进程切换 ,但这不影响结果。如果进程1在 ldrex 后被打断,进程2在执行 strex 后会把Exclusive清除。进程2执行后,在转到进程1去,进程1在执行 strex 时因为 Exclusive 被清除,则不会执行strex的内容,直接把会temp置1,比较temp不为0,跳转到到1继续执行,这样就保证运行的结果。
1: ldrex [result], [v->counter] //把counter的值给result,并设置全局标记“Exclusive” add [result], [result], [i] //result+1 并把值传给 result strex [temp], [result], [v->counter] //把result的值给counter,成功temp=0,清除“Exclusive” teq [temp], #0 //temp和0比较 bne 1b //temp不等于0,则跳转到最开始的1继续操作
在linux中,内核提供了两组原子操作接口:一组是针对整数进行操作;另一组是针对单独的位进行操作。
原子操作对整数类型定义:
- atomic_t v = ATOMIC_INIT(0); //定义原子变量v并初始化为0
- atomic_read(atomic_t *v); //返回原子变量的值
- atomic_set(atomic_t *v); //设置原子变量的值
- atomic_add(int i, atomic_t *v) //给一个原子变量加上i
- atomic_add_return(int i, atomic_t *v) //给一个原子变量加上i,并将变量v的最新值返回
- atomic_sub(int i, atomic_t *v) //给一个原子变量减去i
- atomic_sub_return(int i, atomic_t *v) //给一个原子变量减去i,将变量v的最新值返回
- void atomic_inc(atomic_t *v); //原子变量增加1
- void atomic_dec(atomic_t *v); //原子变量减少1
- int atomic_dec_and_test(atomic_t *v); //自减操作后测试其是否为0,为0则返回true,否则返回false。
原子操作对位类型定义:
- void set_bit(nr, void *addr); //设置位,设置addr地址的第nr位,所谓设置位是将位写为1
- void clear_bit(nr, void *addr); //清除位,清除addr地址的第nr位,所谓清除位是将位写为0
- void change_bit(nr, void *addr);//改变位,addr地址的第nr位进行反置。
- test_bit(nr, void *addr);//测试位,上述操作返回addr地址的第nr位。
- int test_and_set_bit(nr, void *addr);//执行test_bit,再执行set_bit
- int test_and_clear_bit(nr, void *addr);//执行test_bit,再执行clear_bit
- int test_and_change_bit(nr, void *addr);//执行test_bit,再执行change_bit
版权声明:本文为weixin_42432281原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。