一步一步走進字符驅動--原子操作

一步一步走進字符驅動--原子操作

閒聊

有一陣子沒跟新博客了,最近發現我以前好多的代碼都不見了...都怪我沒有及時備份.在這裏提醒下,一定要多備份你們的代碼資料.到時候別硬盤打不開之類的悲劇也降臨了,近幾天羣裏有個朋友問我要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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章