linux并发控制之原子操作
转载原子操作指的是在执行过程中不会被别的代码路径所中断的操作。
分为两类:整型原子操作 和 位原子操作。
特点:
1.任何情况下操作都是原子的。
2.都依赖底层的CPU的原子操作来实现,所以和CPU架构密切相关。
注意:
1.原子操作在不同体系架构实现的方法不同,基本采用汇编实现
2.上述的整数原子函数集仅针对32位,内核中关于64位有另一套函数
3.对于SMP系统,内核还提供了local_t数据类型,实现对单个CPU的整数原子操作,接口函数仅将atomic_替换成local_即可,定义于linux/asm-generic/local.h
一.整型原子操作
定义于#include<asm/atomic.h>
分为 定义,获取,加减,测试,返回。
void atomic_set(atomic_t *v,int i); //设置原子变量v的值为i
atomic_t v = ATOMIC_INIT(0); //定义原子变量v,并初始化为0;
atomic_read(atomic_t* v); //返回原子变量v的值;
void atomic_add(int i, atomic_t* v); //原子变量v增加i;
void atomic_sub(int i, atomic_t* v);
void atomic_inc(atomic_t* v); //原子变量增加1;
void atomic_dec(atomic_t* v);
int atomic_inc_and_test(atomic_t* v); //先自增1,然后测试其值是否为0,若为0,则返回true,否则返回false;
int atomic_dec_and_test(atomic_t* v);
int atomic_sub_and_test(int i, atomic_t* v); //先减i,然后测试其值是否为0,若为0,则返回true,否则返回false;
注意:只有自加,没有加操作
int atomic_add_return(int i, atomic_t* v); //v的值加i后返回新的值;
int atomic_sub_return(int i, atomic_t* v);
int atomic_inc_return(atomic_t* v); //v的值自增1后返回新的值;
int atomic_dec_return(atomic_t* v);
二.位原子操作
定义于#include<asm/bitops.h>
分为 设置,清除,改变,测试
void set_bit(int nr, volatile void* addr); //设置地址addr的第nr位,所谓设置位,就是把位写为1;
void clear_bit(int nr, volatile void* addr); //清除地址addr的第nr位,所谓清除位,就是把位写为0;
void change_bit(int nr, volatile void* addr); //把地址addr的第nr位反转;
int test_bit(int nr, volatile void* addr); //返回地址addr的第nr位;
int test_and_set_bit(int nr, volatile void* addr); //测试并设置位;若addr的第nr位非0,则返回true; 若addr的第nr位为0,则返回false;
int test_and_clear_bit(int nr, volatile void* addr); //测试并清除位;
int test_and_change_bit(int nr, volatile void* addr); //测试并反转位;
上述操作等同于先执行test_bit(nr,voidaddr)然后在执行xxx_bit(nr,voidaddr)
举个简单例子:
为了实现设备只能被一个进程打开,从而避免竞态的出现
static atomic_t scull_available = ATOMIC_INIT(1); //init atomic
在scull_open 函数和scull_close函数中:
int scull_open(struct inode *inode, struct file *filp)
{
struct scull_dev *dev; // device information
dev = container_of(inode->i_cdev, struct scull_dev, cdev);
filp->private_data = dev; // for other methods
if(!atomic_dec_and_test(&scull_available)){
atomic_inc(&scull_available);
return -EBUSY;
}
return 0; // success
}
int scull_release(struct inode *inode, struct file *filp)
{
atomic_inc(&scull_available);
return 0;
}
同样也可以用位原子操作实现
本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
上一篇:linux并发控制之总章
下一篇:linux并发控制之中断屏蔽
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
Go并发之原子操作
代码中的加锁操作因为涉及内核态的上下文切换会比较耗时、代价比较高。针对基本
golang java 数据库 原子操作 赋值 -
【并发】CAS原子操作
CAS是Compare And Swap的缩写,直译就是比较并交换。CAS是现代CPU广泛支持的一种对内存中的共享数据进行操作的一种特殊指令,这
linux 多线程 并发 无锁 Java -
Java并发编程之原子操作
原子操作类
java 开发语言 jvm 赋值