Linux信号量以及互斥体
一、信號量簡介
相比于自旋鎖,信號量可以使線程進入休眠狀態,比如A與B、C合租了一套房子,這個房子只有一個廁所,一次只能一個人使用。某一天早上A去上廁所了,過了一會B也想用廁所,因為A在廁所里面,所以B只能等到A用來了才能進去。B要么就一直在廁所門口等著,等A出來,這個時候就相當于自旋鎖。B也可以告訴A,讓A出來以后通知他一下,然后B繼續回房間睡覺,這個時候相當于信號量。可以看出,使用信號量會提高處理器的使用效率,畢竟不用一直傻乎乎的在那里“自旋”等待。但是,信號量的開銷要比自旋鎖大,因為信號量使線程進入休眠狀態以后會切換線程,切換線程就會有開銷。總結一下信號量的特點:
- ①、因為信號量可以使等待資源線程進入休眠狀態,因此適用于那些占用資源比較久的場合。
- ②、因此信號量不能用于中斷中,因為信號量會引起休眠,中斷不能休眠。
- ③、如果共享資源的持有時間比較短,那就不適合使用信號量了,因為頻繁的休眠、切換線程引起的開銷要遠大于信號量帶來的那點優勢。
信號量有一個信號量值,相當于一個房子有10把鑰匙,這10把鑰匙就相當于信號量值為10。因此,可以通過信號量來控制訪問共享資源的訪問數量,如果要想進房間,那就要先獲取一把鑰匙,信號量值減1,直到10把鑰匙都被拿走,信號量值為0,這個時候就不允許任何人進入房間了,因為沒鑰匙了。如果有人從房間出來,那他要歸還他所持有的那把鑰匙,信號量值加1,此時有1把鑰匙了,那么可以允許進去一個人。相當于通過信號量控制訪問資源的線程數,在初始化的時候將信號量值設置的大于1,那么這個信號量就是計數型信號量,計數型信號量不能用于互斥訪問,因為它允許多個線程同時訪問共享資源。如果要互斥的訪問共享資源那么信號量的值就不能大于1,此時的信號量就是一個二值信號量。
二、信號量API函數
Linux內核使用semaphore結構體表示信號量,結構體如下:
struct semaphore {raw_spinlock_t lock;unsigned int count;struct list_head wait_list; };要想使用信號量就得先定義,然后初始化信號量。有關信號量的API函數如下表所示:
| DEFINE_SEAMPHORE(name) | 定義一個信號量,并且設置信號量的值為1。 |
| void sema_init(struct semaphore *sem,int val) | 初始化信號量sem,設置信號量值為val。 |
| void down(struct semaphore *sem) | 獲取信號量,因為會導致休眠,因此不能在中斷中使用。 |
| int down_trylock(struct semaphore *sem) | 嘗試獲取信號量,如果能獲取到信號量就獲取,并且返回0。如果不能就返回非0,并且不會進入休眠。 |
| int down_interruptible(struct semaphore *sem) | 獲取信號量,和down類似,只是使用down進入休眠狀態的線程不能被信號打斷。而使用此函數進入休眠以后是可以被信號打斷的。 |
| void up(struct semaphore *sem) | 釋放信號量。 |
信號量的使用框架如下:
struct semaphore sem; /*定義信號量 */ sema_init(&sem,1);/*初始化信號量*/ down ( &sem ) ;/*申請信號量*/ /*臨界區*/ up(&sem);/*釋放信號量*/三、互斥體簡介
在FreeRTOS和UCOS中也有互斥體,將信號量的值設置為1就可以使用信號量進行互斥訪問了,雖然可以通過信號量實現互斥,但是Linux提供了一個比信號量更專業的機制來進行互斥,它就是互斥體——mutex。互斥訪問表示一次只有一個線程可以訪問共享資源,不能遞歸申請互斥體。在編寫Linux驅動的時候遇到需要互斥訪問的地方建議使用mutex。Linux內核使用mutex結構體表示互斥體,定義如下:
struct mutex{atomic_t count;spinlock_t wait_lock; };在使用mutex之前要先定義一個mutex變量。在使用mutex的時候要注意如下幾點:
- ①、mutex可以導致休眠,因此不能在中斷中使用mutex,中斷中只能使用自旋鎖。
- ②、和信號量一樣,mutex保護的臨界區可以調用引起阻塞的API函數。
- ③、因為一次只有一個線程可以持有mutex,因此,必須由mutex的持有者釋放mutex。并且mutex不能遞歸上鎖和解鎖。
四、互斥體API函數
有關互斥體的API函數如下表所示:
| DEFINE_MUTEX(name) | 定義并初始化一個mutex變量。 |
| void mutex_init(mutex *lock) | 初始化mutex。 |
| void mutex_lock(struct mutex *lock) | 獲取mutex,也就是給mutex上鎖。如果獲取不到就進休眠。 |
| void mutex_unlock(struct mutex *lock) | 釋放mutex,也就給mutex解鎖。 |
| int mutex_trylock(struct mutex *lock) | 嘗試獲取mutex,如果成功就返回1,如果失敗就返回0。 |
| int mutex_is_locked(struct mutex *lock) | 判斷mutex是否被獲取,如果是的話就返回1,否則返回0。 |
| int mutex_ interruptible(struct mutex *lock) | 使用此函數獲取信號量失敗進入休眠以后可以被信號打斷。 |
互斥體的使用框架如下:
struct mutex lock;/*定義一個互斥體*/ mutex_init(&lock);/*初始化互斥體*/mutex_lock(&lock);/*上鎖*/ /*臨界區*/ mutex_unlock(&lock);/*解鎖*/Linux信號量、互斥體就講解到這里啦!
總結
以上是生活随笔為你收集整理的Linux信号量以及互斥体的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos7 卸载service服务
- 下一篇: KDD 2016 | node2vec: