简体   繁体   English

Mutex 是否调用系统调用?

[英]Does Mutex call a system call?

CRITICAL_SECTION locking (enter) and unlocking (leave) are efficient because CS testing is performed in user space without making the kernel system call that a mutex makes. CRITICAL_SECTION 锁定(进入)和解锁(离开)是高效的,因为 CS 测试是在用户空间中执行的,而无需进行互斥锁进行的内核系统调用。 Unlocking is performed entirely in user space, whereas ReleaseMutex requires a system call.解锁完全在用户空间执行,而 ReleaseMutex 需要系统调用。

I just read these sentences in this book .我刚刚在这本书中读到了这些句子。
What the kernel system call mean?内核系统调用是什么意思? Could you give me the function's name?你能告诉我函数的名字吗?

I'm a English newbie.我是英语新手。 I interpreted them like this.我是这样解释它们的。

  • CS testing doesn't use a system call. CS 测试不使用系统调用。
  • Mutex testing uses a system call.(But I don't know the function name. Let me know)互斥测试使用系统调用。(但我不知道函数名。让我知道)
  • CS unlocking doesn't call a system call. CS 解锁不会调用系统调用。
  • Mutex unlocking requires a system call.(But I don't know the function name. Let me know)互斥锁解锁需要系统调用。(但我不知道函数名。让我知道)

Another question.另一个问题。

  • I think CRITICAL_SECTION might call WaitForSingleObject or family functions.我认为 CRITICAL_SECTION 可能会调用 WaitForSingleObject 或系列函数。 Don't these functions require a system call?这些函数不需要系统调用吗? I guess they do.我猜他们会。 So CS testing doesn't use a system call is very weird to me.所以CS 测试不使用系统调用对我来说很奇怪。

The implementation of critical sections in Windows has changed over the years, but it has always been a combination of user-mode and kernel calls.多年来,Windows 中临界区的实现发生了变化,但它始终是用户模式和内核调用的组合。

The CRITICAL_SECTION is a structure that contains a user-mode updated values, a handle to a kernel-mode object - EVENT or something like that, and debug information. CRITICAL_SECTION 是一个结构,它包含用户模式更新的值、内核模式对象的句柄 - EVENT 或类似的东西,以及调试信息。

EnterCriticalSection uses an interlocked test-and-set operation to acquire the lock. EnterCriticalSection 使用互锁的测试和设置操作来获取锁。 If successful, this is all that is required (almost, it also updates the owner thread).如果成功,这就是所需要的(几乎,它还会更新所有者线程)。 If the test-and-set operation fails to aquire, a longer path is used which usually requires waiting on a kernel object with WaitForSignleObject .如果 test-and-set 操作无法获取,则使用更长的路径,这通常需要使用WaitForSignleObject等待内核对象。 If you initialized with InitializeCriticalSectionAndSpinCount then EnterCriticalSection may spin an retry to acquire using interlocked operation in user-mode.如果您使用InitializeCriticalSectionAndSpinCount进行初始化,则EnterCriticalSection可能会在用户模式下使用互锁操作旋转重试以获取。

Below is a diassembly of the "fast" / uncontended path of EnterCriticialSection in Windows 7 (64-bit) with some comments inline以下是 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

So the bottom line is that if the thread does not need to block it will not use a system call, just an interlocked test-and-set operation.所以底线是,如果线程不需要阻塞,它不会使用系统调用,只是一个互锁的测试和设置操作。 If blocking is required, there will be a system call.如果需要阻塞,就会有系统调用。 The release path also uses an interlocked test-and-set and may require a system call if other threads are blocked.释放路径也使用互锁的测试和设置,如果其他线程被阻塞,可能需要系统调用。

Compare this to Mutex which always requires a system call NtWaitForSingleObject and NtReleaseMutant将此与始终需要系统调用NtWaitForSingleObjectNtReleaseMutant Mutex 进行比较

Calling to the kernel requires a context switch , which is takes a small (but measurable) performance hit for every context switch.调用内核需要上下文切换,每次上下文切换都会对性能造成很小(但可衡量)的影响。 The function in question is ReleaseMutex() itself.有问题的函数是ReleaseMutex()本身。

The critical section functions are available in kernel32.dll (at least from the caller's point of view - see comments for discussion about ntdll.dll ) and can often avoid making any calls into the kernel.临界区函数在kernel32.dll中可用(至少从调用者的角度来看 - 请参阅有关ntdll.dll讨论的评论)并且通常可以避免对内核进行任何调用。

It is worthwhile to know that Mutex objects can be accessed from different processes at the same time.值得注意的是,Mutex 对象可以同时从不同的进程访问。 On the other hand, CRITICAL_SECTION objects are limited to one process.另一方面, CRITICAL_SECTION对象仅限于一个进程。

To my knowledge critical sections are implemented using semaphores.据我所知,关键部分是使用信号量实现的。

The critical section functions are implemented in NTDLL, which implements some runtime functions in user mode and passes control so the kernel for others (system call).临界区函数在 NTDLL 中实现,它在用户模式下实现一些运行时函数,并将控制权传递给其他内核(系统调用)。 The functions in kernel32.dll are simple function forwarders. kernel32.dll 中的函数是简单的函数转发器。

Mutexes on the other hand are kernel objects and require a system call as such.另一方面,互斥体是内核对象,因此需要系统调用。 The kernel calls them "mutants", by the way (no joke).顺便说一下,内核称它们为“突变体”(不是开玩笑)。

Critical section calls only transition to kernel mode if there is contention and only then if they can't relieve the contention by spinning.临界区仅在存在争用时才调用转换到内核模式,并且仅当它们无法通过旋转解除争用时才调用。 In that case the thread blocks and calls a wait function – that's a system call.在这种情况下,线程会阻塞并调用一个等待函数——这是一个系统调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM