您的位置:首页 > 运维架构 > Linux

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

2017-10-21 16:06 645 查看

并发:

多个执行单元同时被执行.

竞态:

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



并发的处理:

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

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

原子操作:

定义:

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

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

atomic_t :

[cpp] view plain copy

typedef struct {

volatile int counter;

} atomic_t;

原子操作函数:

整型原子操作:

[cpp] view plain copy

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 :

[cpp] view plain copy

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);

对原子变量进行加/减,自增/自减操作,并返回新的值:

[cpp] view plain copy

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);

位原子操作:

[cpp] view plain copy

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 :

[cpp] view plain copy

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

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

如果减 一 为 0 !true 为 假 ,if 里面的原子变量加一恢复到 0

{

atomic_inc(&canopen);

return -EBUSY;

}

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

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

[cpp] view plain copy

atomic_inc(&canopen);

4,应用程序测试:

在应用程序里面打开驱动程序:

[cpp] view plain copy

fd = open("/dev/buttons", O_RDWR);

if (fd < 0)

{

printf("can't open!\n");

return -1;

}

当有两个应用程序打开同一这个驱动的时候,打印 can't open! .
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: