现在的位置: 首页 > 综合 > 正文

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

2013年11月14日 ⁄ 综合 ⁄ 共 2074字 ⁄ 字号 评论关闭
文章目录

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

闲聊

有一阵子没跟新博客了,最近发现我以前好多的代码都不见了...都怪我没有及时备份.在这里提醒下,一定要多备份你们的代码资料.到时候别硬盘打不开之类的悲剧也降临了,近几天群里有个朋友问我要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;
}

抱歉!评论已关闭.