加鎖爲什麼慢:有些同步原語是操作系統的內核對象,調用該原語會帶來昂貴的上下文切換(用戶態切換到內核態)代價;
自旋鎖的介紹:先循環N次,期間如果拿到鎖則不用進內核態了,沒拿到才進內核態去等待;例子: CriticalSection可以設成自旋,也可設成非自旋;
用戶態和內核態介紹
爲什麼要有用戶態和內核態: 由於需要限制不同的程序之間的訪問能力, 防止他們獲取別的程序的內存數據, 或者獲取外圍設備的數據, 併發送到網絡, CPU劃分出兩個權限等級 -- 用戶態和內核態。
Linux進程的4GB地址空間,3G-4G部分大家是共享的,是內核態的地址空間,這裏存放在整個內核的代碼和所有的內核模塊,以及內核所維護的數據。write,send等系統調用會調用內核中的代碼來完成操作,這時必須切換到Ring0,然後進入3GB-4GB中的內核地址空間去執行這些代碼完成操作。這樣,用戶態的程序就不能隨意操作內核地址空間,具有一定的安全保護作用。
1)用戶態切換到內核態的3種方式
a. 系統調用:系統調用的機制其核心還是使用了操作系統爲用戶特別開放的一箇中斷來實現,例如Linux的int 80h中斷。
b. 異常:當CPU在執行運行在用戶態下的程序時,發生了某些事先不可知的異常,這時會觸發由當前運行進程切換到處理此異常的內核相關程序中,也就轉到了內核態,比如缺頁異常。
c. 外圍設備的中斷:外圍設備完成用戶請求的操作後,會向CPU發出相應的中斷信號,這時CPU會暫停執行下一條即將要執行的指令轉而去執行與中斷信號對應的處理程序,如果先前執行的指令是用戶態下的程序,那麼這個轉換的過程自然也就發生了由用戶態到內核態的切換。比如硬盤讀寫操作完成,系統會切換到硬盤讀寫的中斷處理程序中執行後續操作等。
2)具體的切換操作
[1] 從當前進程的描述符中提取其內核棧的ss0及esp0信息。
[2] 使用ss0和esp0指向的內核棧將當前進程的cs,eip,eflags,ss,esp信息保存起來,這個過程也完成了由用戶棧到內核棧的切換過程,同時保存了被暫停執行的程序的下一條指令。
[3] 將先前由中斷向量檢索得到的中斷處理程序的cs,eip信息裝入相應的寄存器,開始執行中斷處理程序,這時就轉到了內核態的程序執行了。