Linux 设备驱动--- 并发 与 竞态 --- atomic_t --- atomic_dec_and_test --- 原子操作

并发:
          多个执行单元同时被执行.

竞态:
          并发的执行单元对资源 ( 硬件资源和软件上的全局变量等 ) 的访问导致的竞争状态.

          

并发的处理:
          处理并发的常用技术是加锁或者互斥,即保证在任何时间只有一个执行单元可以操作共享资源.

          在 Linux 内核中主要通过 semaphore 机制 (信号量)和spin_lock 机制 (自旋锁)实现.

原子操作:
定义:
原子操作指的是在执行过程中不会被别的代码所中断的操作.

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

atomic_t  :
typedef struct {
volatile int counter;
} atomic_t;
原子操作函数:
整型原子操作:
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);
先设值,后返回。


实例 --- 原子操作:
1,定义一原子变量:
在程序开头定义原子变量,初始化为 1 :

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

2,在 open 函数里检测原子变量值:
如果没有进程在使用该驱动 ,原子变量值 为 1 ,将原子变量减 一 为 0 ,函数返回 true ,再 !true 为 假 ,if 里面的代码不执行;

这样打开了、并使用该驱动, 原子变量变为 0;

如果再有进程来打开驱动程序,0-1 = 负1,返回 false ,if 条件成立,运行里面的代码,将原子变量加一恢复到  0,程序返回;

    if (!atomic_dec_and_test(&canopen))
    {
        atomic_inc(&canopen);
        return -EBUSY;
    }

3,在退出时 close 函数 恢复原子变量值:
最后, 在应用程序退出时 close 函数, 自增 恢复原子变量值为 1:

atomic_inc(&canopen);

4,应用程序测试:
在应用程序里面打开驱动程序:

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

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

--------------------- 
作者:_借我你的一生_ 
来源:CSDN 
原文:https://blog.csdn.net/yikai2009/article/details/8650221 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值