我所理解liunx下的原子操作

  • Post author:
  • Post category:其他



什么是原子操作:

原子操作是为了确保对一个整型数据的更改具有排他性。原子操作就是要么不执行,一旦执行就会执行完成,是不可被打断的一个,或一系列的动作,即在完成任务前不会被其他事件所打断,就像原子不可被分割成颗粒一样。单处理中,可以用单条指令完成的指令可以被看成是一个原子操作。软件中的原子操作依赖于硬件原子操作的支持。当然原子操作,也可以当引用计数使用。

其实本质上原子操作和锁实现同样的功能,都是为了保护共享对象,它具有原子性,和顺序性。原子性确保指令执行期间不被打断,要么全部执行,要么根本不执行。而顺序性确保即使两条或多条指令出现在独立的执行线程中,甚至独立的处理器上,它们本该执行的顺序依然要保持。


原子操作会被打断,但不会影响结果:

在执行原子操作的过程中,它可能会被其它执行流打断,比如中断、进程切换 ,但这不影响结果。如果进程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 版权协议,转载请附上原文出处链接和本声明。