linux-原子操作
来源:互联网 发布:无印良品有淘宝店吗 编辑:程序博客网 时间:2024/06/05 15:10
何为原子操作?以前认为原子是组成物质的最小单位,是不可分割的。因此就利用原子这个词,表示某个操作也是原子的,不可分割的,不能被打断,这就是原子操作。原子操作又分为整型原子操作 和 位原子操作。如果我们想使用原子操作,linux的内核都给我们做好了,我们只需要搞定原理然后去用就好了。linux 的原子操作都依赖底层的CPU的原子操作来实现,所以和CPU架构密切相关。原子操作在不同体系架构实现的方法不同,基本采用汇编实现,我们一般所说的操作都是针对32位的ARM的。
整型原子操作接口
1,设置原子的值void atomic_set(atomic_t *v,int i); //设置原子变量v的值为iatomic_t v = ATOMIC_INIT(0); //定义原子变量v,并初始化为0;2 获取原子变量的值/*原子的读取atomic_t变量的值,v是这个变量的地址\ 返回原子变量v的值;*/atomic_read(atomic_t* v); 3 原子变量的加、减 void atomic_add(int i, atomic_t* v); //原子变量v增加i;void atomic_sub(int i, atomic_t* v); //原子变量v减少i;4 原子变量的自增和自减void atomic_inc(atomic_t* v); //原子变量增加1;void atomic_dec(atomic_t* v); //原子变量减少1;5 操作并检测//先自增1,然后测试其值是否为0,若为0,则返回true,否则返回false;int atomic_inc_and_test(atomic_t* v); int atomic_dec_and_test(atomic_t* v);//先减i,然后测试其值是否为0,若为0,则返回true,否则返回false; int atomic_sub_and_test(int i, atomic_t* v); 注意:只有自加,没有加操作6 操作并返回//v的值加i后返回新的值;int atomic_add_return(int i, atomic_t* v); int atomic_sub_return(int i, atomic_t* v); //v的值自增1后返回新的值; int atomic_inc_return(atomic_t* v); int atomic_dec_return(atomic_t* v);
位原子操作接口
1 设置位void set_bit(int nr, volatile void* addr); //设置地址addr的第nr位,所谓设置位,就是把位写为1;2 清除位void clear_bit(int nr, volatile void* addr); //清除地址addr的第nr位,所谓清除位,就是把位写为0;3 改变位void change_bit(int nr, volatile void* addr); //把地址addr的第nr位反转;4 测试位int test_bit(int nr, volatile void* addr); //返回地址addr的第nr位;5 测试并操作位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)
原子操作多用于多线程的竟态,使设备只能被一个进程打开。
//定义原子变量并初始化为1 static atomic_t atomic_available = ATOMIC_INIT(1); int led_open(struct inode *inode, struct file *filp) { /*如果没有进程在使用该驱动 ,原子变量值 为 1 , 将原子变量减 一 为 0 ,函数返回 true ,再 !true 为 假 , if里面的代码不执行,继续执行下下面的程序。*/ if(!atomic_dec_and_test(&atomic_available)) { /* 如果再有进程来打开驱动程序,0-1 = 负1,返回 false , if 条件成立,运行里面的代码,将原子变量加一恢复到0,程序返回*/ printk(KERN_ERR "already open!\n"); atomic_inc(&atomic_available); return -EBUSY; //already open } printk(KERN_INFO "led open!\n"); filp->private_data = atomic_available; return 0; } int led_release(struct inode *inode ,struct file *filp) { printk(KERN_INFO "led release!\n"); /*推出时恢复为1 */ atomic_inc(&atomic_available); return 0; }
我们可以写个程序进行测试
int main() { int fd; fd = open("/dev/leds",O_RDWR); if(fd == -1) { printf("open error!!\n"); return -1; } sleep(10); printf("close fd!\n"); close(fd); return 0; }
我们先打开led设备,然后延时10s之后再关闭。我们可以刚打开10s之内,使用cat /dev/leds ,发现还是可以打开的。如果使用了原子操作我们在去测试,发现打印出设备正在忙,证明我们的原子操作起作用了。
阅读全文
1 0
- Linux 原子操作
- Linux原子操作
- linux 原子操作
- linux 原子操作
- linux原子操作
- Linux 原子操作
- Linux 原子操作
- Linux 原子操作
- linux 原子操作
- linux中的原子操作
- 【转】Linux 原子操作
- Linux 原子操作
- linux gcc原子操作
- Linux 原子操作
- linux原子操作
- Linux Driver原子操作
- linux原子操作
- Linux 原子操作
- ZOJ-3802:Easy 2048 Again(2048游戏 状态压缩dp)
- Flask学习笔记--6
- jQuery的一些用法
- (0.1+0.7)*10!=8?
- H
- linux-原子操作
- ARP协议
- java基础之xml
- 缓存式的字符输入输出流
- 搜索专题: HDU1312Red and Black
- Java菜鸟学习日记19
- [codeforces 832D]Misha, Grisha and Underground
- L1-045. 宇宙无敌大招呼
- 【C++】模拟String___引用计数写实拷贝