信號量、互斥鎖、自旋鎖、原子操作


linux內核中有多種內核鎖,內核鎖的作用是:

多核處理器下,會存在多個進程處於內核態的情況,而在內核態下,進程是可以訪問所有內核數據的,因此要對共享數據進行保護,即互斥處理;
 

linux內核鎖機制有信號量互斥鎖自旋鎖還有原子操作

 

一、信號量(struct semaphore):

是用來解決進程/線程之間的同步和互斥問題的一種通信機制,是用來保證兩個或多個關鍵代碼不被並發調用。

信號量(Saphore)由一個值和一個指針組成,指針指向等待該信號量的進程。信號量的值表示相應資源的使用情況。信號量S>=0時,S表示可用資源的數量。執行一次P操作意味着請求分配一個資源,因此S的值減1;當S<0時,表示已經沒有可用資源,S的絕對值表示當前等待該資源的進程數。請求者必須等待其他進程釋放該類資源,才能繼續運行。而執行一個V操作意味着釋放一個資源,因此S的值加1;若S<0,表示有某些進程正在等待該資源,因此要喚醒一個等待狀態的進程,使之運行下去。 

信號量是選擇睡眠的方式來對共享工作停止訪問的。

也就是說信號量通過PV操作同步解決了進程/線程對臨界資源利用的沖突問題;

 

二、互斥鎖:(mutex_lock)

互斥鎖同樣也是對線程間(不能對進程)同步和互斥的一種另一種機制。

互斥鎖更多的是強調對共享資源的鎖定作用,當一個線程占用了當前共享資源,使用互斥鎖將其lock住之后,其他線程就無法訪問,必須等到unlock之后,其他線程才能利用共享資源里面的內容;

 互斥鎖是選擇睡眠的方式來對共享工作停止訪問的。

也就是說互斥鎖通過對共享資源的鎖定和互斥解決利用資源沖突問題;

 

 

 三、自旋鎖(spin_lock):

是為實現保護共享資源而提出一種鎖機制。其實,自旋鎖與互斥鎖比較類似,它們都是為了解決對某項資源的互斥使用。無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執行單元獲得鎖。但是兩者在調度機制上略有不同。對於互斥鎖,如果資源已經被占用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那里看是否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是因此而得名。

 

 

四、原子操作:

Reference:

http://blog.sina.com.cn/s/blog_6d7fa49b01014q7p.html

http://blog.csdn.net/vividonly/article/details/6599502

http://blog.csdn.net/williamwang2013/article/details/8517380

http://blog.csdn.net/yikai2009/article/details/8650221

4.1、Linux原子概念:

所謂原子操作,就是“不可中斷的一個或一系列操作”。

原子操作,就是不能被更高等級中斷搶奪優先的操作。你既然提這個問題,我就說深一點。由於操作系統大部分時間處於開中斷狀態,所以,一個程序在執行的時候可能被優先級更高的線程中斷。而有些操作是不能被中斷的,不然會出現無法還原的后果,這時候,這些操作就需要原子操作。就是不能被中斷的操作。

硬件級的原子操作:在單處理器系統(UniProcessor)中,能夠在單條指令中完成的操作都可以認為是“原子操作”,因為中斷只發生在指令邊緣。在多處理器結構中(Symmetric Multi-Processor)就不同了,由於系統中有多個處理器獨立運行,即使能在單條指令中完成的操作也有可能受到干擾。在X86平台生,CPU提供了在指令執行期間對總線加鎖的手段。CPU上有一根引線#HLOCK pin連到北橋,如果匯編語言的程序中在一條指令前面加上前綴"LOCK",經過匯編以后的機器代碼就使CPU在執行這條指令的時候把#HLOCK pin的電位拉低,持續到這條指令結束時放開,從而把總線鎖住,這樣同一總線上別的CPU就暫時不能通過總線訪問內存了,保證了這條指令在多處理器環境中的原子性。對於其他平台的CPU,實現各不相同,有的是通過關中斷來實現原子操作(sparc),有的通過CMPXCHG系列的指令來實現原子操作(IA64)。本文主要探討X86平台下原子操作的實現。

 

 

4.2、Linux內核兩組原子操作接口:

1、原子整數操作

原子操作通常針對int或bit類型的數據,但是Linux並不能直接對int進行原子操作,而只能通過atomic_t的數據結構來進行。

定義於#include<asm/atomic.h>

圖1.1      內核中的整數原子操作函數

 

2、內核中提供的一些主要位原子操作函數。同時內核還提供了一組與上述操作對應的非原子位操作函數,名字前多兩下划線。由於不保證原子性,因此速度可能執行更快。

定義於#include<asm/bitops.h>

大話Linux內核中鎖機制之原子操作、自旋鎖

圖1.2      內核中的位原子操作函數

 

 1 void atomic_set(atomic_t *v,int i);    //設置原子變量v的值為i
 2 atomic_t v = ATOMIC_INIT(0);     //定義原子變量v,並初始化為0;
 3 
 4 atomic_read(atomic_t* v);     //返回原子變量v的值;
 5 
 6 void atomic_add(int i, atomic_t* v);     //原子變量v增加i;
 7 void atomic_sub(int i, atomic_t* v);    
 8 
 9 void atomic_inc(atomic_t* v);     //原子變量增加1;
10 void atomic_dec(atomic_t* v);     
11 
12 int atomic_inc_and_test(atomic_t* v);        //先自增1,然后測試其值是否為0,若為0,則返回true,否則返回false;
13 int atomic_dec_and_test(atomic_t* v);       //先自減1,然后測試其值是否為0,若為0,則返回true,否則返回false 14 int atomic_sub_and_test(int i, atomic_t* v);     //先減i,然后測試其值是否為0,若為0,則返回true,否則返回false;
15 //注意:只有自加,沒有加操作
16 
17 int atomic_add_return(int i, atomic_t* v);   //v的值加i后返回新的值;
18 int atomic_sub_return(int i, atomic_t* v);  
19 int atomic_inc_return(atomic_t* v);     //v的值自增1后返回新的值;
20 int atomic_dec_return(atomic_t* v);    

 

實例代碼:

在scull_open 函數和scull_close函數中:

如果沒有進程使用該驅動 ,原子變量值 為 1 ,將原子變量減 一 為 0 ,函數返回 true ,再 !true 為 假 ,if 里面的代碼不執行這樣打開了、並使用該驅動, 原子變量變為 0;

如果再有進程來打開驅動程序,0-1 = 負1,返回 false ,if 條件成立,運行里面的代碼,將原子變量加一恢復到  0,程序返回;

最后, 在應用程序退出時 close 函數, 自增 恢復原子變量值為 1:

 1 static atomic_t scull_available = ATOMIC_INIT(1);      //init atomic
 2 
 3 int scull_open(struct inode *inode, struct file *filp)
 4 {
 5     struct scull_dev *dev;         // device information
 6 
 7     dev = container_of(inode->i_cdev, struct scull_dev, cdev);
 8     filp->private_data = dev;         // for other methods 
 9     if(!atomic_dec_and_test(&scull_available)){
10         atomic_inc(&scull_available);
11         return -EBUSY;
12     }
13     return 0;         // success 
14 }
15 
16 int scull_release(struct inode *inode, struct file *filp)
17 {
18     atomic_inc(&scull_available);
19     return 0;
20 }

 

 

 

 

 

以上總結幾點:

互斥鎖與信號量的區別:

1、信號量一般以同步的方式對共享資源進行控制,而互斥鎖通過互斥的方式對共享資源對其進行控制;

2、信號量可以對進程的共享資源進行控制,而互斥鎖不行;

3、信號量的值為非負整數,而互斥鎖的值只能為0或1;

4、互斥量的加鎖和解鎖必須由同一線程分別對應使用,信號量可以由一個線程釋放,另一個線程得到;mutex和二值信號量的區別在於mutex必須是同一個進程來釋放

 

自旋鎖與互斥鎖的區別:

1、因為自旋鎖不會引起調用者睡眠,所以效率比較高

2、自旋鎖比較適用於鎖使用者保持鎖時間比較短的情況。

3、自旋鎖容易造成死鎖,所以需要安全使用它;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM