4.8.2原子操作

   避免干扰的最简单方法就是保证操作的原子性,即操作必须在一条单独的指令内执行。有两种类型的原子操作,即位图操作和数学的加减操作。

 1.位图操作

在内核的很多地方用到位图,例如内存管理中对空闲页的管理,位图还有一个广泛的用途就是简单的加锁,例如提供对打开设备的互斥访问。关于位图的操作函数如下:

以下函数的参数中,addr指向位图。

void set_bit(int nr, volatile void *addr):设置位图的第nr位。

void clear_bit(int nr, volatile void *addr): 清位图的第nr

void change_bit(int nr, volatile void *addr): 改变位图的第nr

int test_and_set_bit(int nr, volatile void *addr): 设置第nr位,并返回该位原来的值,且两个操作是原子操作,不可分割。

int test_and_clear_bit(int nr, volatile void *addr): 清第nr为,并返回该位原来的值,且两个操作是原子操作。

int test_and_change_bit(int nr, volatile void *addr):改变第nr位,并返回该位原来的值,且这两个操作是原子操作。

这些操作利用了LOCK_PREFIX宏,对于SMP内核,该宏是总线锁指令的前缀,对于单CPU这个宏不起任何作用。这就保证了在SMP环境下访问的原子性。

 2.算术操作

有时候位操作是不方便的,取而代之的是需要执行算术操作,即加、减操作及加1、减1操作。典型的例子是很多数据结构中的引用计数域count(如inode结构)。这些操作的原子性是由atomic_t数据类型和表4.14中的函数保证的。atomic_t的类型在include/ i386/atomic.h定义如下:

   typedef struct { volatile int counter; } atomic_t;

 

4.14 原子操作

函数

说明

atomic_read(v)

返回*v

atomic_set(v,i)

*v设置成i

Atomic_add(I,v)

*v增加i

Atomic_sub(I,v)

*v中减去I

Atomic_inc(v)

*v1

Atomic_dec(v)

*v中减去1

Atomic_dec_and_test(v)

*v中减去1,如果结果非空就返回1;否则返回0

Atomic_inc_and_test_greater_zero(v)

*v1,如果结果为正就返回1;否则就返回0

Atomic_clear_mask(mask,addr)

清除由mask所指定的addr中的所有位。

Atomic_set_mask(mask,addr)

设置由mask所指定的addr中的所有位。