原子操作概念:
可以保证指令以原子的方式执行---执行的过程不被打断,内核共提供了两组原子操作接口分别是
1、一组针对整数进行操作
2、一组针对单独的位进行操作
下面详述之
一、原子整数操作
数据类型:atomic_t 这里之所以引入新的数据类型的原因有2,第一个,让原子整数操作函数只接受atomic_t的数据类型,可以确保该数据类型不会误传给其他非原子整数操作函数,第二个,防止被编辑器优化。
头文件: <asm/atomic.h>
范例:
atomic_t v; //定义v
atomic_t u = ATOMIC_INIT(0); //定义u 并把它初始化为 0
操作:
atomic_set(&v,4); //v=4 (原子地)
atomic_add(2,&v); //v = v + 2 = 6 (原子地)
atomic_inc(&v); //v = v + 1=7 (原子地)
如果需要将atomic_t转化为int,用atomic_read()完成:
printk("%d",atomic_read(&v)); //打印出7
应用举例:原子整数操作最常见的用途就是实现计数器。使用一个复杂的锁机制来保护一个单纯的计数器是很笨拙的。
注意点1:使用atomic_t型的数据类型,只能将该数据当作24位来用。原因是因为在SPARC的体系结构上,这种体系结构是缺乏指令级的支持,他的解决办法,是在32位的int类型的低8位嵌入一个锁。
注意点2:原子操作通常是内联函数,往往是通过内嵌汇编指令来实现的。
拓展:
二、原子位操作
数据类型:无特殊的数据类型 (int)由位操作函数是普通的内存地址进行操作的,所以不像原子整型对应atomic_t,这里没有特殊的数据类型,相反,只要指针指向了任何你希望的数据,你就可以对它进行操作。
头文件: <asm/bitops.h>
范例:
unsigned long word = 0;
set_bit(0,&word);
set_bit(1,&word);
补充:
内核还提供了一组与上述操作对应的非原子位函数,其名字前缀多两个下划线。内核还提供了两个例程用来从指定的地址开始搜索第一个被设置(或未被设置)的位:
int find_first_bit(unsigned long *addr,unsigned int size)
int find_first_zero_bit(unsigned long *addr,unsigned int size)