Mutex 是否调用系统调用?

发布于 2024-10-19 22:23:25 字数 595 浏览 1 评论 0原文

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

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

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

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

另一个问题。

  • 我认为 CRITICAL_SECTION 可能会调用 WaitForSingleObject 或系列函数。这些功能不需要系统调用吗?我想他们会的。所以CS测试不使用系统调用对我来说很奇怪。

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. Unlocking is performed entirely in user space, whereas ReleaseMutex requires a system call.

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.
  • 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.
  • 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. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

东风软 2024-10-26 22:23:26

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

临界区函数在 kernel32.dll 中可用(至少从调用者的角度来看 - 请参阅有关 ntdll.dll 的讨论的注释),并且通常可以避免进行任何调用进入内核。

值得注意的是,互斥对象可以同时从不同的进程访问。另一方面,CRITICAL_SECTION 对象仅限于一个进程。

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.

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.

It is worthwhile to know that Mutex objects can be accessed from different processes at the same time. On the other hand, CRITICAL_SECTION objects are limited to one process.

梦旅人picnic 2024-10-26 22:23:26

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

临界区函数在 NTDLL 中实现,NTDLL 在用户模式下实现一些运行时函数,并将控制权传递给其他函数(系统调用)。 kernel32.dll 中的函数是简单的函数转发器。

另一方面,互斥锁是内核对象,因此需要系统调用。顺便说一句,内核称它们为“突变体”(不是开玩笑)。

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). The functions in kernel32.dll are simple function forwarders.

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).

小清晰的声音 2024-10-26 22:23:26

仅当存在争用并且无法通过旋转缓解争用时,临界区才会调用转换到内核模式。在这种情况下,线程会阻塞并调用等待函数——这是一个系统调用。

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.

池木 2024-10-26 22:23:25

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

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

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

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

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

因此,底线是,如果线程不需要阻塞,则它不会阻塞使用系统调用,只是一个互锁的测试和设置操作。如果需要阻塞,就会有系统调用。释放路径还使用互锁的测试和设置,并且如果其他线程被阻止,则可能需要系统调用。

将此与始终需要系统调用 NtWaitForSingleObject 和 NtReleaseMutant 的 Mutex 进行比较

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.

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.

EnterCriticalSection uses an interlocked test-and-set operation to acquire the lock. 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. If you initialized with InitializeCriticalSectionAndSpinCount then EnterCriticalSection may spin an retry to acquire using interlocked operation in user-mode.

Below is a diassembly of the "fast" / uncontended path of EnterCriticialSection in Windows 7 (64-bit) with some comments inline

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文