Linux 并发与竞态(一)原子操作atomtic

文章目录

  • 1.什么是原子操作?目的是什么?
  • 2.原子操作函数:
        • 整型原子操作
        • 位原子操作
  • 3.原子操作【实例代码】
        • 1. 定义原子变量
        • 2.在 open 函数里检测原子变量值
        • 3.在退出时 close 函数 恢复原子变量值
        • 4. 应用程序测试

1.什么是原子操作?目的是什么?

atomic原子操作:“不可被中断的一个或一系列操作”

同一时刻,多个线程要么不执行这段代码,要么将这段代码全部
.
子操作不被任何别的进程打断和访问。

目的: 为避免由于“读->改->写”指令引起的竞争条件,原子操作以保证多个线程并发对内存操作某个值得准确性。


2.原子操作函数:

https://www.cnblogs.com/wanghuaijun/p/7705045.html

原子操作分为两类: 位 和 整型变量

整型原子操作

void atomic_set(atomic_t *v, int i); //设置原子变量v的值为i  
atomic_t v = ATOMIC_INIT(0);         //定义原子变量v, 并初始化为0  
atomic_read(atomic_t *v);            //获得原子变量的值,返回原子变量的值

void atomic_add(int i, atomic_t *v); //原子变量+i  
void atomic_sub(int i, atomic_t *v); //原子变量-i  
void atomic_inc(atomic_t *v);        //原子变量+1            
void atomic_dec(atomic_t *v);        //原子变量-1  位变量:

//原子变量执行自增,自减和减操作后 ,测试其是否为0,为 0 则返回 true,否则返回 false
int atomic_inc_and_test(atomic_t *v);   
int atomic_dec_and_test(atomic_t *v);              
int atomic_sub_and_test(int i, atomic_t *v);  

//对原子变量进行加/减,自增/自减操作,并返回新的值
int atomic_add_return(int i, atomic_t *v);  
int atomic_sub_return(int i, atomic_t *v);  
int atomic_inc_return(atomic_t *v);  
int atomic_sub_return(atomic_t *v); 

位原子操作

void set_bit(nr, void *addr);         //将addr地址的nr位 置为1  
void clear_bit(nr, void *addr);       //将addr地址的nr位 清0  
void change_bit(nr, void *addr);      //对addr地址的nr位 反置  
int test_bit(nr, void *addr);         //返回addr地址的nr位  
int test_and_set_bit(nr, void *addr);  
int test_and_clear_bit(nr, void *addr);  
int test_and_change_bit(nr, void *addr);  先设值,后返回。

3.原子操作【实例代码】

1. 定义原子变量

static atomic_t canopen = ATOMIC_INIT(1);     //定义原子变量并初始化为1

2.在 open 函数里检测原子变量值

/*对原子变量执行自减后测试是否为0,为0返回true*/
if(!atomic_dec_and_test(&canopen))
{
    /*对原子变量自增*/
    atomic_inc(&canopen);
    return -EBUSY;
}

3.在退出时 close 函数 恢复原子变量值

atomic_inc(&canopen);

4. 应用程序测试

fd = open("/dev/buttons", O_RDWR);  
if (fd < 0)  
{  
    printf("can't open!\n");  
    return -1;  
}

当有两个应用程序打开同一这个驱动的时候,打印 can’t open!

你可能感兴趣的:(LINUX,内核驱动)