Windows事件等待学习笔记(一)—— 临界区自旋锁
Windows事件等待學習筆記(一)—— 臨界區&自旋鎖
- 基礎知識
- 演示代碼
- 案例一
- 案例二
- LOCK
- 單行代碼原子操作
- 多行代碼原子操作
- 臨界區
- 演示代碼
- 手動實現
- 自旋鎖
- 分析 KeAcquireSpinLockAtDpcLevel
- 總結
基礎知識
并發:是指多個線程在同時執行
同步:則是保證在并發執行的環境中各個線程可以有序的執行
演示代碼
注意:如果線程中的代碼只對局部變量進行訪問,就不存在并發的問題;只有當訪問全局變量的時候,才需要關注并發的問題
案例一
DWORD dwVal = 0; //全局變量線程中的代碼:dwVal++; //只有一行 安全嗎?答案:
dwVal++; 對應的匯編代碼:mov eax,[0x12345678]add eax,1 //當第一個線程執行到這里時,產生了線程切換的話//第二個線程也執行到這里時,將會出現邏輯錯誤mov [0x12345678],eax案例二
當將案例一的三行匯編代碼改為一行時:
INC DWORD PTR DS:[0x12345678] //一行匯編指令,安全嗎?答案:若當前系統為單核時,安全;但如果當前CPU為多核時,不安全(兩個核有可能同時執行一行指令)
解決方案:改為LOCK INC DWORD PTR DS:[0x12345678]
LOCK
描述:在多核CPU的情況下,保證只有一個CPU能訪問帶有LOCK指令內存
可以帶LOCK前綴的指令:
BT, BTS, BTR, BTC (mem, reg/imm) XCHG, XADD (reg, mem / mem, reg) ADD, OR, ADC, SBB (mem, reg/imm) AND, SUB, XOR (mem, reg/imm) NOT, NEG, INC, DEC (mem)單行代碼原子操作
原子操作相關API:
InterlockedIncrement InterlockedExchangeAdd InterlockedDecrement InterlockedFlushSList InterlockedExchange InterlockedPopEntrySList InterlockedCompareExchange InterlockedPushEntrySListInterlockedIncrement 反匯編:
多行代碼原子操作
關鍵代碼A //N行代碼要求原子操作 關鍵代碼B //單獨加LOCK可以嗎? 關鍵代碼C .......答案:不行,試想一下,當第一個線程執行到關鍵代碼B,第二個線程就執行完關鍵代碼A時,此時雖然第二個線程無法執行關鍵代碼B,但卻有可能會先執行關鍵代碼C
解決方案:臨界區
臨界區
描述:一次只允許一個線程進入直到離開
實現思路:加鎖(全局變量)
演示代碼
DWORD dwFlag = 0; //實現臨界區的方式就是加鎖//鎖:全局變量 進去加一 出去減一if(dwFlag == 0) //進入臨界區 { dwFlag = 1 .....................dwFlag = 0 //離開臨界區 }問題:上述演示代碼安全嗎?
答案:仍不安全,當第一個線程通過if判斷并進入if內部,但還未來得及執行dwFlag=1時,第二個線程也有可能通過if判斷從而進入if語句內部
手動實現
進入臨界區:
Lab:mov eax,1lock xadd [Flag],eaxcmp eax,0jz endLabdec [Flag]//線程等待Sleep.. endLab:ret離開臨界區
lock dec [Flag]自旋鎖
小提示:單核和多核雖然使用的是同一份內核文件,但里面的代碼是有區別的
單核 ntoskrnl.exe 反匯編:
多核 ntoskrnl.exe 反匯編:
分析 KeAcquireSpinLockAtDpcLevel
多核:
單核:
總結
(查看不同版本的KeAcquireSpinLockAtDpcLevel函數)
總結
以上是生活随笔為你收集整理的Windows事件等待学习笔记(一)—— 临界区自旋锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows APC学习笔记(二)——
- 下一篇: Windows事件等待学习笔记(二)——