sem就是一個睡眠鎖.如果有一個任務試圖獲得一個已被持有的訊號量時,訊號量會將其推入等待隊列,然後讓其睡眠。這時處理器獲得自由去執行其它代碼。當持有訊號量的進程將訊號量釋放後,在等待隊列中的一個任務將被喚醒,從而便可以獲得這個訊號量。訊號量一般在用進程上下文中.它是為了防止多進程同時訪問一個共用資源(臨界區).
spin_lock叫自旋鎖.就是當試圖請求一個已經被持有的自旋鎖.這個任務就會一直進行 忙迴圈——旋轉——等待,直到鎖重新可用(它會一直這樣,不釋放CPU,它只能用在短時間加鎖).它是為了防止多個CPU同時訪問一個共用資源(臨界區).它一般用在中斷上下文中,因為中斷上下文不能被中斷,也不能被調度.
自旋鎖對訊號量
需求 建議的加鎖方法
低開銷加鎖 優先使用自旋鎖
短期鎖定 優先使用自旋鎖
長期加鎖 優先使用訊號量
中斷上下文中加鎖 使用自旋鎖
持有鎖是需要睡眠、調度 使用訊號量
進程間的sem.線程間的sem與核心中的sem的功能就很類似.
進程間的sem,線程間的sem功能是一樣的.只是線程的sem,它在同一個進程空間,他的初始化,使用更方便.
進程間的sem,就是處理序間通訊的一部分,使用semget,semop等系統調用來完成.
核心中的sem 被鎖定,就等於被調用的進程佔有了這個sem.其它進程就只能進行睡眠隊列.這與進程間的sem基本一致.
區別 |
Spin_lock |
semaphore |
保護的對象 |
一段代碼 |
一個裝置(必要性不強), 一個變數, 一段代碼 |
保護區可被搶佔 |
不可以 |
可以。 |
可允許在保護對象(代碼)中休眠 |
不可以 |
可以。但最好不這樣。 |
保護區能否被中斷打斷 |
可以,這樣容易引發死結。 最好是關了中斷再使用此鎖。 因為有可能中斷處理常式也需要得到同一個鎖。 |
可以。 |
其它功能 |
|
可完成同步,有傳達資訊的能力。 |
| |
|
|
試圖佔用鎖不成功後,進程的表現 |
不放開CPU,自己自旋。 |
進入一個等待隊列。 |
釋放鎖後,還有其它進程等待時,核心如何處理 |
某CPU(不是進程)最先發現鎖已釋放,則它就得到了鎖。 |
從等待隊列中選一個出來佔用此sem. |
核心對使用者的要求 |
被保護的代碼執行時間要短,是原子的, 不能主動的休眠。 不能調用有可以休眠的核心功能。 |
|
風險 |
發生死結 |
|
| |
不允許鎖的持有人二次請求同一個鎖。 |
不允許鎖的持有人二次請求同一個鎖。 |
訊號量在生產者與消費者模式中可以進行同步。
當sem的down和UP分別出現在對立函數中(讀,寫函數),其實這就是在傳達一種資訊。表示當前是否有資料可讀的資訊。
read_somthing()
{
down(裝置) 佔用了此裝置 此時沒有其它人都使用此裝置上的所有操作(函數)
if(有資料)
{
讀完它。
()
}
else
{
up(裝置)
down(有資料的sem)sem=1表示有資料,為0表示無資料。
}
}
write_somthing()
{
down(裝置) 佔用了此裝置 此時沒有其它人都使用此裝置上的所有操作(函數)
if(有資料)
{
不寫。
up(裝置)
return
}
else
{
寫入資料
up(有資料的sem)sem=1表示有資料,為0表示無資料。
up(裝置)
return;
}
}