一步一步走进字符驱动--原子操作

一步一步走进字符驱动--原子操作

闲聊

有一阵子没跟新博客了,最近发现我以前好多的代码都不见了...都怪我没有及时备份.在这里提醒下,一定要多备份你们的代码资料.到时候别硬盘打不开之类的悲剧也降临了,近几天群里有个朋友问我要D3D的代码..我好久没接触那东西了,于是乎去找.结果发现找不到了..悲剧死....好了,言归正传.开始今天的教程..

原子操作

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

linux中又支持两类原子操作,一类是整形变量.一类是位变量.它们的共同点都是原子操作.内核代码可以安全的调用它们而不会被打断.

整形原子操作

原子操作定义: arm/include/asm/atomic.h

typedef struct {
        int counter;
} atomic_t;

1:设置原子变量的值

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

2:获取原子变量的值

atomic_read(v);	 //返回原子变量的值

3:原子变量加/减

static inline void atomic_add(int i, atomic_t *v);	//原子变量加i
static inline void atomic_sub(int i, atomic_t *v);	//原子变量减i

4:原子变量自增/自减

void atomic_add(1, v);	 //原子变量自增1
void atomic_sub(1, v);	 //原子变量自减1

5:操作并测试

#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_sub_and_test(i, v) 	(atomic_sub_return(i, v) == 0)

上述原子变量对自身进行操作之后与0进行比较.==0返回true,否则返回false

:此处没有加操作

6:操作并返回

static inline int atomic_add_return(int i, atomic_t *v);
static inline int atomic_sub_return(int i, atomic_t *v);
#define atomic_inc_return(v)    (atomic_add_return(1, v))
#define atomic_dec_return(v)    (atomic_sub_return(1, v))

上述操作是对原子变量先进行自增自减和加减操作,后返回新的值

位原子操作

所属头文件:asm/bitops.h

1:设置位

void set_bit(nr,void*addr)

设置addr地址的第nr位为1

2清除位

void clear_bit(nr,void*addr)

设置addr地址的第nr位为0

3:改变位

void change_bit(nr,void* addr)

设置addr地址的第nr位为反置

4:测试位

test_bit(nr,void*addr)

返回addr地址的第nr位的值

5:测试并操作位

int test_and_set_bit(nr,void*addr)
int test_and_clear_bit(nr,void*addr)
int test_and_change_bit(nr,void*addr)

上述操作相当于执行test_bit后执行相应的操作


下面给出一份代码--实现设备只能被打开一次

struct device_dev{
struct 	 cdev cdev;
atomic_t	 atomic;
};
//初始化原子操作
atomic_set(&g_devp->atomic,1);
int atomic_open(struct inode *_pinod, struct file *_pfile)
{
printk(KERN_INFO "%d\n",atomic_read(&g_devp->atomic));
//atomic被初始化为1.那么第一次条件测试的时候,if(false),那么就成功打开,否则.永远失败
//初始化在模块加载函数内.atomic_set(&g_devp->atomic,1);
if(!atomic_dec_and_test(&g_devp->atomic)){
atomic_inc(&g_devp->atomic);
printk(KERN_INFO "error %d\n",atomic_read(&g_devp->atomic));
return -EBUSY;
}
printk(KERN_INFO "successful %d\n",atomic_read(&g_devp->atomic));
return 0;
}
int atomic_release(struct inode *_pinod, struct file *_pfile)
{
atomic_inc(&g_devp->atomic);
return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值