一步一步走進字符驅動--自旋鎖

一步一步走進字符驅動--自旋鎖

前面說到原子操作和今天的自旋鎖,以及信號量等.都是爲了防止搶佔式操作系統和SMP所帶來的競態的發生.那麼什麼叫競態呢?相信很多學過linux系統編程和window 開發的都知道.當一個進程在訪問一個公共資源時,由於時間片時間到或者被搶佔等,會導致其他進程運行,有可能也訪問該資源.那麼就會修改這份資源,導致本來的進程再此操作這份資源時,資源內的數據已被修改..由於這種情況,所以操作系統才引出各種鎖來鎖定公共資源來達到資源的保護.

今天我們大致看一下自旋鎖.

簡介:

自旋鎖是一種典型的對臨界區資源進行互斥訪問的手段,其名稱是根據它的工作方式得來的.爲了獲得自旋鎖,在某CPU上運行的代碼需先執行一個原子操作,該操作測試並設置某一內存變量,由於它是原子操作,所以在該操作完成之前其他執行單元不能訪問這個內存變量.如果測試結果表明鎖已經空閒,則程序獲得這個自旋鎖並繼續執行,如果測試表明鎖仍被佔用,程序將在一個小的循環內重複這個"測試並設置"操作,即進行所謂的"自旋",就是原子打轉.

自旋鎖定義:	linux/Spinlock.h
typedef struct spinlock {
union {
struct raw_spinlock rlock;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
#define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
struct {
u8 __padding[LOCK_PADSIZE];
struct lockdep_map dep_map;
};
#endif
};
} spinlock_t;

1:定義自旋鎖

spinlock_t lock;

2:初始化自旋鎖

spin_lock_init(lock); //該宏用於動態初始化自旋鎖

3:獲得自旋鎖

static inline void spin_lock(spinlock_t *lock); //獲取自旋鎖,若能獲取,則立即返回,否則自選在這等待獲取

static inline int spin_trylock(spinlock_t *lock); //嘗試獲取自旋鎖,若能獲取則返回TRUE,否則返回FALSE,不原地自選

4:釋放自旋鎖

static inline void spin_unlock(spinlock_t *lock); //釋放獲得的自旋鎖

示例:

/*定義一個自旋鎖*/

spinlock_t lock;

spin_lock_init(lock);

spin_lock(&lock); //獲取自旋鎖

/*臨界區資源*/

spin_unlock(&lock); //釋放自旋鎖

由於自旋鎖在自旋時不能被中斷打斷,否則將鎖死,所以延伸出帶中斷的自旋鎖

static inline void spin_lock_irq(spinlock_t *lock);
static inline void spin_unlock_irq(spinlock_t *lock);
#define spin_lock_irqsave(spinlock_t *lock, flags);
static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
static inline void spin_lock_bh(spinlock_t *lock);
static inline void spin_unlock_bh(spinlock_t *lock);

自旋鎖主要針對單SMP和單CPU但支持搶佔式的情況,對於單CPU和內核不支持搶佔式的話,自旋鎖會退化成空操作.

自旋鎖實現設備打開唯一性,示例代碼:

spinlock_t 	lock;
int	 global_count = 0;	//定義文件被打開的次數
int 	global_mem_open(struct inode *inode, struct file *filp)
{
/*將設備結構體指針賦給文件私有數據指針*/
struct globalmem_dev *devp;
devp = container_of(inode->i_cdev,struct globalmem_dev,cdev);
filp->private_data = devp;
spin_lock(&lock);
if (global_count) { //文件被打開
return -EBUSY;
}
global_count++;//增加使用計數器
spin_unlock(&lock);
/*判斷文件打開的標誌*/
return 0;
}
int 	global_mem_release(struct inode *inode, struct file *filp)
{
spin_lock(&lock);
global_count--;//減少使用計數器
spin_unlock(&lock);
return 0;
}


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