spinlock和Semaphore信號量的區別?
Mutex是壹把鑰匙,壹個人拿了就可進入壹個房間,出來的時候把鑰匙交給隊列的第壹個。壹般的用法是用於串行化對criticalsection代碼的訪問,保證這段代碼不會被並行的運行。
Semaphore是壹件可以容納N人的房間,如果人不滿就可以進去,如果人滿了,就要等待有人出來。對於N=1的情況,稱為binarysemaphore。壹般的用法是,用於限制對於某壹資源的同時訪問。
Binarysemaphore與Mutex的差異:
在有的系統中Binarysemaphore與Mutex是沒有差異的。在有的系統上,主要的差異是mutex壹定要由獲得鎖的進程來釋放。而semaphore可以由其它進程釋放(這時的semaphore實際就是個原子的變量,大家可以加或減),因此semaphore可以用於進程間同步。Semaphore的同步功能是所有系統都支持的,而Mutex能否由其他進程釋放則未定,因此建議mutex只用於保護criticalsection。而semaphore則用於保護某變量,或者同步。
另壹個概念是spinlock,這是壹個內核態概念。spinlock與semaphore的主要區別是spinlock是busywaiting,而semaphore是sleep。對於可以sleep的進程來說,busywaiting當然沒有意義。對於單CPU的系統,busywaiting當然更沒意義(沒有CPU可以釋放鎖)。因此,只有多CPU的內核態非進程空間,才會用到spinlock。Linuxkernel的spinlock在非SMP的情況下,只是關irq,沒有別的操作,用於確保該段程序的運行不會被打斷。其實也就是類似mutex的作用,串行化對criticalsection的訪問。但是mutex不能保護中斷的打斷,也不能在中斷處理程序中被調用。而spinlock也壹般沒有必要用於可以sleep的進程空間。
---------------------------------------------------------------------------------------------
內核同步措施
為了避免並發,防止競爭。內核提供了壹組同步方法來提供對***享數據的保護。我們的重點不是介紹這些方法的詳細用法,而是強調為什麽使用這些方法和它們之間的差別。
Linux使用的同步機制可以說從2.0到2.6以來不斷發展完善。從最初的原子操作,到後來的信號量,從大內核鎖到今天的自旋鎖。這些同步機制的發展伴隨Linux從單處理器到對稱多處理器的過度;伴隨著從非搶占內核到搶占內核的過度。鎖機制越來越有效,也越來越復雜。
目前來說內核中原子操作多用來做計數使用,其它情況最常用的是兩種鎖以及它們的變種:壹個是自旋鎖,另壹個是信號量。我們下面就來著重介紹壹下這兩種鎖機制。
自旋鎖
自旋鎖是專為防止多處理器並發而引入的壹種鎖,它在內核中大量應用於中斷處理等部分(對於單處理器來說,防止中斷處理中的並發可簡單采用關閉中斷的方式,不需要自旋鎖)。
自旋鎖最多只能被壹個內核任務持有,如果壹個內核任務試圖請求壹個已被爭用(已經被持有)的自旋鎖,那麽這個任務就會壹直進行忙循環——旋轉——等待鎖重新可用。要是鎖未被爭用,請求它的內核任務便能立刻得到它並且繼續進行。自旋鎖可以在任何時刻防止多於壹個的內核任務同時進入臨界區,因此這種鎖可有效地避免多處理器上並發運行的內核任務競爭***享資源。
事實上,自旋鎖的初衷就是:在短期間內進行輕量級的鎖定。壹個被爭用的自旋鎖使得請求它的線程在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應該被持有時間過長。如果需要長時間鎖定的話,最好使用信號量。
自旋鎖的基本形式如下:
spin_lock(mr_lock);
//臨界區
spin_unlock(mr_lock);
因為自旋鎖在同壹時刻只能被最多壹個內核任務持有,所以壹個時刻只有壹個線程允許存在於臨界區中。這點很好地滿足了對稱多處理機器需要的鎖定服務。在單處理器上,自旋鎖僅僅當作壹個設置內核搶占的開關。如果內核搶占也不存在,那麽自旋鎖會在編譯時被完全剔除出內核。
簡單的說,自旋鎖在內核中主要用來防止多處理器中並發訪問臨界區,防止內核搶占造成的競爭。另外自旋鎖不允許任務睡眠(持有自旋鎖的任務睡眠會造成自死鎖——因為睡眠有可能造成持有鎖的內核任務被重新調度,而再次申請自己已持有的鎖),它能夠在中斷上下文中使用。
死鎖:假設有壹個或多個內核任務和壹個或多個資源,每個內核都在等待其中的壹個資源,但所有的資源都已經被占用了。這便會發生所有內核任務都在相互等待,但它們永遠不會釋放已經占有的資源,於是任何內核任務都無法獲得所需要的資源,無法繼續運行,這便意味著死鎖發生了。自死瑣是說自己占有了某個資源,然後自己又申請自己已占有的資源,顯然不可能再獲得該資源,因此就自縛手腳了。
信號量
Linux中的信號量是壹種睡眠鎖。如果有壹個任務試圖獲得壹個已被持有的信號量時,信號量會將其推入等待隊列,然後讓其睡眠。這時處理器獲得自由去執行其它代碼。當持有信號量的進程將信號量釋放後,在等待隊列中的壹個任務將被喚醒,從而便可以獲得這個信號量。
信號量的睡眠特性,使得信號量適用於鎖會被長時間持有的情況;只能在進程上下文中使用,因為中斷上下文中是不能被調度的;另外當代碼持有信號量時,不可以再持有自旋鎖。
信號量基本使用形式為:
staticDECLARE_MUTEX(mr_sem);//聲明互斥信號量
if(down_interruptible(mr_sem))
//可被中斷的睡眠,當信號來到,睡眠的任務被喚醒
//臨界區
up(mr_sem);
信號量和自旋鎖區別
雖然聽起來兩者之間的使用條件復雜,其實在實際使用中信號量和自旋鎖並不易混淆。註意以下原則:
如果代碼需要睡眠——這往往是發生在和用戶空間同步時——使用信號量是唯壹的選擇。由於不受睡眠的限制,使用信號量通常來說更加簡單壹些。如果需要在自旋鎖和信號量中作選擇,應該取決於鎖被持有的時間長短。理想情況是所有的鎖都應該盡可能短的被持有,但是如果鎖的持有時間較長的話,使用信號量是更好的選擇。另外,信號量不同於自旋鎖,它不會關閉內核搶占,所以持有信號量的代碼可以被搶占。這意味者信號量不會對影響調度反應時間帶來負面影響。
自旋鎖對信號量
需求建議的加鎖方法
低開銷加鎖優先使用自旋鎖
短期鎖定優先使用自旋鎖
長期加鎖優先使用信號量
中斷上下文中加鎖使用自旋鎖
持有鎖是需要睡眠、調度使用信號量
linux怎麽實現二進制信號?
用echo直接可以十六進制寫到文件裏去。echo-e-nx11x22>test這樣就把兩個字節數據0x11和0x22寫入到了文件test中