歡迎您光臨本站 註冊首頁

linux設備驅動中的併發控制——信號量

←手機掃碼閱讀     火星人 @ 2014-03-08 , reply:0

1 信號量
信號量(semaphore)是用於保護臨界區的一種常用方法,他的使用方式與自旋鎖類似,只有得到信號量的進程才能 執行臨界區代碼,與自旋鎖不同的是,進程不會原地打轉而是進入休眠等待狀態.
LINUX系統中與信號量相關的操作主要有如下幾種:
1)定義信號量
struct semaphore sem;
2)初始化信號量
void sema_init(struct semphore *sem,int val);//將信號量值設為val
void init_MUTEX(struct semaphore *sem);//初始化一個互斥的信號量,值設為1
void init_MUTEX_LOCKED(struct semaphore *sem);//初始化一個信號量,值為
此外可以使用如下宏定義和初始化一個信號量(name)
DECLARE_MUTEX(name)
DECLARE_MUTEX_LOCKED(name)//值為0
3)獲取信號量
void down(struct semaphore *sem);
該函數用於獲得信號量sem,會導致休眠,因此不能在中斷上下文中使用
int down_interruptible(struct semaphore *sem);
與down()類似,不同在於該函數進入休眠狀態的進程能被信號打斷,信號也會導致該函數返回,此時該函數的返回值非0
int down_trylock(struct semaphore *sem);
該函數嘗試獲得信號量sem,如果成功,它就獲得該信號量並返回0,否則,返回非0.他不會導致調用者休眠,可以在中斷上下文中使用.
在使用down_interruptible()獲取信號量時,對返回值一般進行檢查,如果非0,通常立即返回-ERESTARTSYS,如:
if (down_interruptible(&sem))
{
return -ERESTARTSYS;
}
4)釋放信號量
void up(struct semaphore *sem);
信號量使用方法如下:
//定義信號量
DECLARE_MUTEX(mount_sem);
down(&mount_sem);
...
critical section//臨界區


...
up(&mount_sem);//釋放信號量
說明:Linux自旋鎖和信號量所採用的"獲取鎖-訪問臨界區-釋放鎖"的方式存在於幾乎所有的多任務操作系統中
下列給出了使用信號量實現設備只能被一個進程打開的實例
static DECLARE_MUTEX(xxx_lock);//定義互斥鎖
static int xxx_open(struct inode *inode,struct file *filp)
{
...
if(down_trylock(&xxx_lock))//獲得打開鎖
return -EBUSY;//設備忙
...
return 0;//成功

}
static int xxx_release(struct inode *inode ,structfile *filp)
{
up(&xxx_lock);//釋放打開鎖
retrun 0;
}

2 信號量用於同步
如果信號量被初始化為0,則它可用於同步, 同步意味著一個執行單元的繼續執行需要等待另一個執行單元完成某事, 保證執行的先後順序.如圖所示,執行單元A執行代碼區域b之前,必須等待執行單元B執行完代碼單元c,信號量可輔助這一同步過程.

圖1: 信號量用於同步

3 完成量用於同步
linux系統提供了一種比信號量更好的同步機制,即完成量,它用於一個執行單元等待另一個執行單元執行完某事.
linux中與completion(完成量)相關的操作有如下四種:
1)定義完成量
struct completion my_completion;
2)初始化完成量
init_completion(&my_completion);
也可以使用下面宏定義和初始化完成量
DECLARE_COMPLETION(my_completion);
3)等待完成量
void wait_completion(struct completion *c);
4)喚醒完成量
void complete(struct completion *c);
void complete_all(struct completion *c);
前者只喚醒一個等待的執行單元,後者釋放所有等待同一完成量的執行單元.下圖描述了使用完成量實現的同步功能.

圖2:完成量實現的同步功能

4 讀寫信號量
讀寫信號量可能引起進程堵塞,但它可以允許N個讀執行單元同時訪問共享資源,而最多只能有一個寫執行單元.因此讀寫信號量是一種相對放寬條件的粒度稍大於信號量的互斥機制.
讀寫信號量涉及的操作有如下5種
1)定義和初始化讀寫信號量
struct rw_semphore my_rws;//定義讀寫信號量
void init_rwsem(struct rw_semphore *my_rws);//初始化讀寫信號量
2)讀信號量獲取
void down_read(struct rw_semphore *my_rws);
int down_read_trylock(struct rw_semphore *my_rws);
3)讀信號量釋放
void up_read(struct rw_semphore *my_rws);
4)寫信號量獲取
void down_write(struct rw_semphore *my_rws);
int down_write_trylock(struct rw_semphore *my_rws);
5)寫信號量釋放
void up_write(struct rw_semphore *my_rws);
讀寫信號量一般這樣使用:
rw_sephore rw_sem;
init_rwsem(&rw_sem);
//讀時獲取信號量
down_read(&rw_sem);
...//臨界資源
up_read(&rw_sem);
//寫時獲取信號量
down_write(&rw_sem);
...//臨界資源
up_write(&rw_sem);


[火星人 ] linux設備驅動中的併發控制——信號量已經有967次圍觀

http://coctec.com/docs/linux/show-post-46648.html