Windows 上的系统调用天生就比 Linux 慢吗?
Posted
技术标签:
【中文标题】Windows 上的系统调用天生就比 Linux 慢吗?【英文标题】:Are system calls on Windows inherently slower than Linux? 【发布时间】:2014-03-30 21:56:54 【问题描述】:我对系统调用的理解是,在 Linux 中,系统调用机制(int 0x80
或其他)被记录并保证在不同内核版本中保持稳定。使用此信息,系统调用直接在 CRT 库中实现,因此当我调用例如printf("a");
这涉及对 CRT 的单个函数调用,其中系统调用被设置和激活。理论上,这可以通过静态编译 CRT(在 Linux 上不常见,但有可能)进一步改进,这样即使是单个函数调用也可以内联。
另一方面,Windows 不记录甚至不保证系统调用机制的一致性。 唯一在 Windows 上进行系统调用的方法是调用从 CRT 完成的ntdll.dll
(或者可能是其他一些*.dll
),所以有两个 涉及的函数调用。如果静态使用 CRT 并且函数被内联(在 Windows 上比在 Linux 上更常见),我们仍然有对 ntdll.dll
的单个函数调用,我们无法摆脱。
所以在我看来,理论上 Windows 上的系统调用本质上会更慢,因为它们总是需要比 Linux 等价物多做一个函数调用。这种理解(以及我上面的解释)是真的吗?
注意:我只是在理论上问这个问题。我知道在进行系统调用时(我认为这总是涉及 2 个上下文切换 - 每个方向一个)额外函数调用的成本可能完全可以忽略不计。
【问题讨论】:
CRT?什么阴极射线管?我不将 C 用于 Windows 应用程序。我的 Delphi 应用程序导入操作系统 DLL 并调用它们。此外,Windows 上的 printf() ?有多少 Windows 应用程序使用 printf 调用? 99.99% 有 GUI,而不是 60 年代侏罗纪的“终端控制台”界面。 @MartinJames CRT 如果您使用的是 C(或者可能也是大多数解释型语言)。在您的情况下,它将是 Delphi 运行时,无论是什么。printf
就是一个例子。任何打开文件或分配堆内存或写入屏幕或其他东西的调用都会执行系统调用
@user2120666 这个问题至少对我来说是非常清楚的,也许是你的理解蒙上了一层阴影?您认为这个问题在哪里混淆了对 CRT 的调用和对内核空间的调用?据我所知,它一直仔细区分两者。
我会将“理论上 Windows 上的系统调用本质上会更慢”更正为“理论上 Windows 上的运行时库调用本质上会更慢”。有了这种变化,您的推理是合理的,尽管正如您所说,差异是微不足道的。请注意,我所做的区别 很重要,因为许多 Windows 程序员不经常使用运行时库,倾向于直接调用 Win32 API。
很难理解这个问题在问什么,为什么它有赏金。这是一个苹果和梨的比较。
【参考方案1】:
在 IA-32 上,有两种方法可以进行系统调用:
使用 int/iret 指令 使用 sysenter/sysexit 指令纯基于 int/iret 的系统调用需要 211 个 CPU 周期(在现代处理器上甚至更多)。 Sysenter/sysexit 需要 46 个 CPU 滴答。如您所见,仅执行用于系统调用的一对指令会引入大量开销。但是任何系统调用实现都涉及内核方面的一些工作(内核上下文的设置,调用及其参数的调度等)。对于基于 int/iret 和 sysenter/sysexit 的系统调用,或多或少真实的高度优化的系统调用将分别花费 ~250 和 ~100 个 CPU 周期。在 Linux 和 Windows 中,大约需要 500 个滴答声。
同时,函数调用(基于 call/ret)每个参数的成本为 2-4 tic + 1。
如您所见,与系统调用成本相比,函数调用引入的开销可以忽略不计。
另一方面,如果您在应用程序中嵌入原始系统调用,则会使其高度依赖硬件。例如,如果您的应用程序带有基于嵌入式 sysenter/sysexit 的原始系统调用将在没有这些指令支持的旧 PC 上执行怎么办?此外,您的应用程序将对操作系统使用的系统调用约定敏感。
ntdll.dll 和 glibc 这样的库是常用的,因为它们为系统服务提供了众所周知的和硬件无关的接口,并在后台隐藏了与内核通信的细节。
如果使用相同的方式跨越用户/内核空间边界,Linux 和 Windows 的系统调用成本大致相同(差异可以忽略不计)。两者都试图在每台特定机器上使用最快的方式。至少从 Windows XP 开始的所有现代 Windows 版本都为 sysenter/sysexit 做好了准备。一些旧版本和/或特定版本的 Linux 仍然可以使用基于 int/iret 的调用。 x64 版本的操作系统依赖于 syscall/sysret 指令,其工作方式与 sysenter/sysexit 类似,可作为 AMD64 指令集的一部分使用。
【讨论】:
+1。无关:我了解到"imbedded" is a word 更正为更经典的拼写。感谢您的有用评论! 没错。这种差异不仅可以忽略不计,而且完全被两个操作系统实际执行各种操作的方式之间的巨大差异所淹没。以上是关于Windows 上的系统调用天生就比 Linux 慢吗?的主要内容,如果未能解决你的问题,请参考以下文章
Windows 上的 HTML5 地理位置比 Linux(Firefox、Chrome、[Chromium])更准确
NSView 的 addSubview 方法天生就慢吗? (可可 OSX)