Mutex是否呼叫系统呼叫?

时间:2011-03-03 02:51:23

标签: windows winapi system mutex critical-section

  

CRITICAL_SECTION锁定(输入)和解锁(离开)是有效的,因为   CS测试在用户空间中执行,而不进行内核系统调用   一个互斥体。解锁完全在用户空间中执行,而ReleaseMutex需要系统调用。

我刚刚在this book中阅读了这些句子 内核系统调用的意思是什么?你能给我这个函数的名字吗?

我是英国新手。我这样解释了它们。

  • CS测试不使用系统调用。
  • 互斥测试使用系统调用。(但我不知道函数名。请告诉我)
  • CS解锁不会呼叫系统呼叫。
  • 互斥锁解锁需要系统调用。(但我不知道功能名称。请告诉我)

另一个问题。

  • 我认为CRITICAL_SECTION可能会调用WaitForSingleObject或族函数。这些功能不需要系统调用吗?我猜他们这样做了。所以 CS测试不使用系统调用对我来说非常奇怪。

4 个答案:

答案 0 :(得分:5)

Windows中关键部分的实现多年来发生了变化,但它始终是用户模式和内核调用的组合。

CRITICAL_SECTION是一个结构,包含用户模式更新值,内核模式对象的句柄 - EVENT或类似的东西,以及调试信息。

EnterCriticalSection使用互锁的测试和设置操作来获取锁定。如果成功,这就是所需要的(几乎,它也会更新所有者线程)。如果set-and-set操作无法获取,则使用更长的路径,这通常需要等待具有WaitForSignleObject的内核对象。如果您使用InitializeCriticalSectionAndSpinCount进行了初始化,则EnterCriticalSection可能会在用户模式下使用互锁操作进行重试。

下面是Windows 7(64位)中EnterCriticialSection的“快速”/无竞争路径的反汇编,其中一些注释是内联的

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

所以最重要的是,如果线程不需要阻塞,它将不会使用系统调用,只是一个互锁的测试和设置操作。如果需要阻止,则会进行系统调用。释放路径还使用互锁的测试和设置,如果其他线程被阻止,则可能需要系统调用。

将此与Mutex进行比较,后者始终需要系统调用NtWaitForSingleObjectNtReleaseMutant

答案 1 :(得分:3)

调用内核需要上下文切换,这对每个上下文切换都会产生很小的(但可测量的)性能影响。有问题的函数是ReleaseMutex()本身。

kernel32.dll中提供了关键部分函数(至少从调用者的角度来看 - 请参阅有关ntdll.dll的讨论的注释)并且通常可以避免对内核进行任何调用。

值得知道,可以同时从不同进程访问Mutex对象。另一方面,CRITICAL_SECTION个对象仅限于一个进程。

答案 2 :(得分:1)

据我所知,关键部分是使用信号量实现的。

关键部分函数在NTDLL中实现,它在用户模式下实现一些运行时函数,并为其他人传递控制权(系统调用)。 kernel32.dll中的函数是简单的函数转发器。

另一方面,

Mutexes 是内核对象,需要系统调用。顺便说一句,内核称它们为“突变体”(不是玩笑)。

答案 3 :(得分:1)

如果存在争用,关键部分调用仅转换到内核模式,并且只有当它们无法通过旋转来缓解争用时才会转换到内核模式。在这种情况下,线程阻塞并调用等待函数 - 这是系统调用。