Windows上的系统调用本质上比Linux慢吗? [英] Are system calls on Windows inherently slower than Linux?

查看:186
本文介绍了Windows上的系统调用本质上比Linux慢吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对系统调用的理解是,在Linux中记录了系统调用机制(int 0x80或其他内容),并保证在不同的内核版本之间稳定.使用此信息,系统调用可直接在CRT库中实现,因此当我调用例如printf("a");这涉及到对CRT的单个功能调用,在该功能中设置并激活了系统调用.从理论上讲,可以通过静态编译CRT(在Linux上不常见,但有可能)来进一步改进它,以便甚至可以内联单个函数调用.

My understanding of system calls is that in Linux the system call mechanism (int 0x80 or whatever) is documented and guaranteed to be stable across different kernel versions. Using this information, the system calls are implemented directly in the CRT library, so that when I call e.g. printf("a"); this involves a single function call to the CRT, where the system call is set up and activated. In theory this can be improved further by statically compiling the CRT (not common on Linux, but a possibility) so that even the single function call may be inlined.

另一方面,Windows不记录甚至不能保证系统调用机制的一致性.在Windows上进行系统调用的唯一方法是调用CRT完成的ntdll.dll(或其他一些*.dll),所以有两个涉及函数调用.如果静态使用CRT并且内联函数被内联(在Windows上比Linux更为常见),我们仍然可以对ntdll.dll进行单个函数调用,这是我们无法摆脱的.

On the other hand, Windows does not document or even guarantee consistency of the system call mechanism. The only way to make a system call on Windows is to call into ntdll.dll (or maybe some other *.dll) which is done from the CRT, so there are two function calls involved. If the CRT is used statically and the function gets inlined (slightly more common on Windows than Linux) we still have the single function call into ntdll.dll that we can't get rid of.

因此,在我看来,从理论上讲,Windows上的系统调用从本质上讲会较慢,因为它们总是必须比Linux上的同等功能执行更多的函数调用.这种理解(和我上面的解释)是真的吗?

So it seems to me that theoretically system calls on Windows will be inherently slower since they always have to do one function call more than their Linux equivalents. Is this understanding (and my explanation above) true?

注意:我纯粹是在理论上问这个问题.我了解到,进行系统调用(我认为它总是涉及2个上下文切换-每个方向一个)时,额外的函数调用的成本可能完全可以忽略不计.

Note: I am asking this purely theoretically. I understand that when doing a system call (which I think always involves 2 context switches - one in each direction) the cost of an extra function call is probably completely negligible.

推荐答案

在IA-32上,有两种方法可以进行系统调用:

On IA-32 there are two ways to make a system call:

  • 使用int/iret指令
  • 使用sysenter/sysexit指令

基于int/iret的纯系统调用需要211个CPU周期(在现代处理器上甚至更多). Sysenter/sysexit需要46个CPU节拍.如您所见,仅执行用于系统调用的一对指令会带来大量开销.但是任何系统调用实现都涉及内核方面的一些工作(内核上下文的设置,调用及其参数的分派等).对于基于int/iret和基于sysenter/sysexit的系统调用,或多或少现实的高度优化的系统调用将分别花费约250和100个CPU周期.在Linux和Windows中,这需要大约500个滴答声.

Pure int/iret based system call takes 211 CPU cycles (and even much more on modern processors). Sysenter/sysexit takes 46 CPU ticks. As you can see execution of only a pair of instructions used for system call introduces significant overhead. But any system call implementation involves some work on the kernel side (setup of kernel context, dispatching of the call and its arguments etc.). More or less realistic highly optimized system call will take ~250 and ~100 CPU cycles for int/iret and sysenter/sysexit based system calls respectively. In Linux and Windows it will take ~500 ticks.

同时,函数调用(基于调用/退出)的成本为每个参数2-4 tic +1.

In the same time, function call (based on call/ret) have a cost of 2-4 tics + 1 for each argument.

如您所见,与系统调用成本相比,函数调用引入的开销可以忽略不计.

As you can see, overhead introduced by function call is negligible in comparision to the system call cost.

另一方面,如果将原始系统调用嵌入到应用程序中,则会使它与硬件高度相关.例如,如果您的带有嵌入式sysenter/sysexit的原始系统调用的应用程序将在不支持这些指令的情况下在旧PC上执行?此外,您的应用程序将对OS使用的系统调用调用约定敏感.

On other hand, if you embed raw system calls in your application, you will make it highly hardware dependent. For example, what if your application with embedded sysenter/sysexit based raw system call will be executed on old PC without these instructions support? In addition your application will be sensitive for system call call convention used by OS.

通常使用诸如ntdll.dll和glibc之类的库,因为它们为系统服务提供了众所周知的且独立于硬件的接口,并且在后台隐藏了与内核进行通信的详细信息.

Such libraries like ntdll.dll and glibc are commonly used, because they provide well-known and hardware independent interface for the system services and hides details of the communication with kernel behind the scene.

如果使用相同的方式跨越用户/内核空间边界,Linux和Windows的系统调用成本大约相同(差异可以忽略不计).两者都试图在每台特定的计算机上使用最快的方式.至少从Windows XP开始的所有现代Windows版本均已为sysenter/sysexit准备.某些旧版本和/或特定版本的Linux仍可以使用基于int/iret的调用. x64版本的操作系统依赖syscall/sysret指令,该指令的工作方式类似于sysenter/sysexit,可作为AMD64指令集的一部分获得.

Linux and Windows have approximately the same cost of system calls if use the same way of crossing the user/kernel space border (difference will be negligible). Both trying to use fastest way possible on each particular machine. All modern Windows versions starting at least from Windows XP are prepared for sysenter/sysexit. Some old and/or specific versions of Linux can still use int/iret based calls. x64 versions of OSes relies to syscall/sysret instructions which works like the sysenter/sysexit and available as part of AMD64 instructions set.

这篇关于Windows上的系统调用本质上比Linux慢吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆