Linux的原子变量

原子变量的操作是一种不可以被打断的操作,原子操作需要硬件支持,因此是架构相关。

类似于汇编的一条汇编指令,不可以被分割。

两种原子变量:

  1. 原子整型操作
  2. 原子位操作

1 原子整型操作

有时候需要共享的资源可能只是一个简单的整型数值。例如在驱动程序中,需要对包含一个count的计数器。这个计数器表示有多少个应用程序打开了设备所对应的设备文件。

通常在设备驱动程序的open()函数中,将count变量加1,在close)函数中,将count减1。如果只有一个应用程序执行打开和关闭操作,那么这里的count计数不会出现问题。但是如果有多个应用程序同时打开或者关闭设备文件,那么就可能导致count多加或者少加,出现错误。为了避免这个问题,内核提供了一个原子整型变量,称为atomict。该变量的定义如下:

typedef struct {
	int counter;
} atomic_t;

不能直接对该结构体变量操作,内核中有专门的函数:

定义atomic_t变量:

#define ATOMIC_INIT(i)	{ (i) }

如:atomic_t cout  =  ATOMIC_INIT(1);

设置变量:

#define atomic_set(v,i)	(((v)->counter) = (i))

读变量:

#define atomic_read(v)	(*(volatile int *)&(v)->counter)

变量加减法:

static inline void atomic_add(int i, atomic_t *v)

static inline void atomic_sub(int i, atomic_t *v)

自加减:

#define atomic_inc(v)		atomic_add(1, v)
#define atomic_dec(v)		atomic_sub(1, v)

加减测试:

#define atomic_inc_and_test(v)	(atomic_add_return(1, v) == 0)  //自加测试
#define atomic_dec_and_test(v)	(atomic_sub_return(1, v) == 0)  //自加测试
#define atomic_inc_return(v)    (atomic_add_return(1, v))  //返回值
#define atomic_dec_return(v)    (atomic_sub_return(1, v))
#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)  //减I测试

2 原子位操作

除了原子整数操作外,还有原子位操作。原子位操作是根据数据的每一位单独进行操作。根据体系结构的不同,原子位操作函数的实现也不同。这些函数的原型如下代码所示。

static inline void set_bit(int nr, volatile unsigned long *addr)
static inline void clear_bit(int nr, volatile unsigned long *addr)
static inline void change_bit(int nr, volatile unsigned long *addr)
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
static inline int test_and_change_bit(int nr, volatile unsigned long *addr)

需要注意的是,原子位操作和原子整数操作是不同的。原子位操作不需要专门定义一个类似atomic-t类型的变量,只需要一个普通的变量指针就可以了。下面对上面的几个函数进行简要的分析:

第01行, set bit()函数将addr变量的第nr位设置为1

第02行, clearbit()函数将addr变量的第nr位设置为0

第03行, change bit()函数将addr变量的第nr位设置为相反的数。

第04行, test and-set bit()函数将addr变量的第nr位设置为1,并返回没有修改之前的值。

第05行, test and-clear-bit()函数将addr变量的第nr位设置为0,并返回没有修改之前的值。

第06行, test and-change-bit()函数将addr变量的第nr位设置为相反的数,并返回没有修改之前的值。

这个和位图很相似,可以参考我的博客:

https://blog.csdn.net/qq_40732350/article/details/83045200

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Linux内核)