2011-03-03 38 views
3

CRITICAL_SECTION鎖定(進入)和解鎖(離開)是有效的,因爲 CS測試是在用戶空間中執行的,而不會執行互斥體產生的內核系統調用 。解鎖完全在用戶空間中執行,而ReleaseMutex需要系統調用。Mutex是否會調用系統調用?

我剛剛在this book中讀到這些句子。
內核系統調用的含義是什麼?你能給我這個函數的名字嗎?

我是英國的新手。我這樣解釋他們。

  • CS測試不使用系統調用。
  • 互斥測試使用系統調用(但我不知道函數名稱,請告訴我)
  • CS解鎖不會調用系統調用。
  • 互斥解鎖需要一個系統調用。(但我不知道該功能的名稱。讓我知道)

另一個問題。

  • 我覺得CRITICAL_SECTION可能會調用WaitForSingleObject或家族函數。這些功能不需要系統調用嗎?我猜他們會。所以CS測試不使用系統調用對我來說很怪異。
+0

互斥使用'CreateMutex'。 – Mehrdad 2011-03-03 03:01:06

+0

自旋鎖實際上是用於內核使用的(當然,您可以在自己的程序中不做任何事情,但這沒有幫助)。以下關於自旋鎖的答案以前是誤導性的,但現在海報已經糾正了它。 – casablanca 2011-03-03 03:28:51

+0

抱歉有關混淆。 – 0xC0000022L 2011-03-03 03:35:19

回答

4

多年來,Windows中關鍵部分的實現已經發生了變化,但它一直是用戶模式和內核調用的結合。

CRITICAL_SECTION是一個包含用戶模式更新值,內核模式對象的句柄-EVENT或類似的東西以及調試信息的結構。

EnterCriticalSection使用互鎖的測試和設置操作來獲取鎖。如果成功,這就是所需要的(幾乎它也會更新所有者線程)。如果set-and-set操作失敗,則使用更長的路徑,這通常需要等待WaitForSignleObject的內核對象。如果用InitializeCriticalSectionAndSpinCount進行初始化,則EnterCriticalSection可能會旋轉重試以在用戶模式下使用互鎖操作進行採集。

下面是EnterCriticialSection「快」 /無競爭的路徑在Windows 7(64位)與一些意見直列

0:000> u rtlentercriticalsection rtlentercriticalsection+35 
ntdll!RtlEnterCriticalSection: 
00000000`77ae2fc0 fff3   push rbx 
00000000`77ae2fc2 4883ec20  sub  rsp,20h 
; RCX points to the critical section rcx+8 is the LockCount 
00000000`77ae2fc6 f00fba710800 lock btr dword ptr [rcx+8],0 
00000000`77ae2fcc 488bd9   mov  rbx,rcx 
00000000`77ae2fcf 0f83e9b1ffff jae  ntdll!RtlEnterCriticalSection+0x31 (00000000`77ade1be) 
; got the critical section - update the owner thread and recursion count 
00000000`77ae2fd5 65488b042530000000 mov rax,qword ptr gs:[30h] 
00000000`77ae2fde 488b4848  mov  rcx,qword ptr [rax+48h] 
00000000`77ae2fe2 c7430c01000000 mov  dword ptr [rbx+0Ch],1 
00000000`77ae2fe9 33c0   xor  eax,eax 
00000000`77ae2feb 48894b10  mov  qword ptr [rbx+10h],rcx 
00000000`77ae2fef 4883c420  add  rsp,20h 
00000000`77ae2ff3 5b    pop  rbx 
00000000`77ae2ff4 c3    ret 

因此,底線是,如果線程並不需要一個diassembly阻止它不會使用系統調用,只是互鎖的測試和設置操作。如果需要阻止,則會有系統調用。釋放路徑也使用互鎖測試和設置,並且如果其他線程被阻塞,可能需要系統調用。

比較這對互斥總是需要一個系統調用NtWaitForSingleObjectNtReleaseMutant

3

調用內核需要上下文切換,這是需要每一個上下文切換一個小的(但可衡量)的性能損失。有問題的功能是ReleaseMutex()本身。

kernel32.dll(至少從調用者的角度來看 - 關於ntdll.dll的討論請參見注釋)中提供了關鍵部分功能,並且通常可以避免向內核發出任何調用。

值得一提的是,互斥對象可以同時從不同的進程訪問。另一方面,CRITICAL_SECTION對象僅限於一個進程。

+0

其他正在討論的函數是等待函數之一,例如用於獲取互斥鎖的'WaitForSingleObject',它又一次引發系統調用。 – casablanca 2011-03-03 03:00:52

+0

@Greg Hewgill:對不起,我必須糾正你的錯誤,但它是一個簡單的函數轉發器(在導出表內)指向'NTDLL.RtlEnterCriticalSection'。 – 0xC0000022L 2011-03-03 03:01:23

+0

系統調用與上下文切換不同。轉換到內核會增加特權級別,但不必保存浮點狀態,重新配置頁表或與上下文切換相關的其他複雜性。 – 2011-03-03 03:03:06

1

據我所知,關鍵部分是使用信號量來實現的。

臨界區功能在NTDLL中實現,NTDLL在用戶模式下實現一些運行時功能,並將控制權交給其他人(系統調用)。 kernel32.dll中的函數是簡單的函數轉發器。

互斥體另一方面是內核對象並且需要系統調用。順便說一下(不是開玩笑),內核稱它們爲「突變體」。

+0

自旋鎖在內核之間相互排斥,因爲它們浪費週期而非常謹慎地使用。用戶線程無法承受旋轉無所事事 - 鎖定測試在用戶空間中完成,但如果鎖定不空閒,線程仍會阻塞。 – casablanca 2011-03-03 03:19:24

+0

@casablanca:對不起,由於使用了InitializeCriticalSectionAndSpinCount,我很困惑。它使用信號量。 – 0xC0000022L 2011-03-03 03:22:39

+0

我已刪除我的downvote。此外,有關'lock'前綴的部分是正確的 - 它確實用於測試鎖,但它與自旋鎖不同。 – casablanca 2011-03-03 03:26:39

1

如果存在爭用,臨界區域調用僅轉換到內核模式,並且只有在它們不能通過旋轉來緩解爭用時纔會進入內核模式。在這種情況下,線程會阻塞並調用一個等待函數 - 這是一個系統調用。