【问题标题】:Why int80h instead of sysenter is used to invoke system calls?为什么使用 int80h 而不是 sysenter 来调用系统调用?
【发布时间】:2012-02-26 12:09:11
【问题描述】:

所有的教科书和 Internet 资源都告诉我 int 80h 是一种用于调用系统调用的陈旧风格,在 x86 平台上已被 SYSENTER 取代。

但我刚刚发现我的系统仍然使用 int 80h。我知道像VDSO,实现系统调用服务的libc包装器之类的教科书内容,但不明白为什么默认情况下仍然使用int 80h。

  1. 谁能告诉我原因? glibc 还是内核太旧?

  2. 现在在什么情况下仍默认使用“int 80h”?

  3. 如何在不安装新 glibc 的情况下强制执行 sysenter?


下面是我的环境:

我在我的 macbook air 2011(Core Duo CPU)上使用 VMWare 安装了一个虚拟机。 虚拟机中的 32 位 Ubuntu 8.04/kernel 2.6.24(使用原始 .config 编译)/libc 2.7。

【问题讨论】:

  • Here 是关于如何确定系统中使用 int 80h 和 sysenter 的哪种机制的一个很好的链接。但这并不能解决我的惊讶,我的系统仍然使用 int 80h。我只是 gdb-ed 一个可执行文件,发现“int 80h”实际上是用 glibc 编码的。也就是在我的情况下,没有使用内核提供的VDSO。
  • 经过一番调查,我确信内核确实提供了 vsyscall 页面。只是glibc被配置为直接使用int 80h。我想这是为 8.04 版本配置这种 libc 的 Ubuntu 人员的选择。

标签: ubuntu linux-kernel system-calls


【解决方案1】:

很可能出于兼容性原因 - 32 位 Ubuntu 被编译为兼容 i386 处理器(好吧,现在可能不是那么旧),它不支持 sysenter(它只出现在 Pentium 2 AFAIK 上)。显然,针对 int 80h 使用 sysenter 确实只对某些类型的处理器有益:

http://articles.manugarg.com/systemcallinlinux2_6.html

因此,如果在一般情况下没有显着的速度提升和更广泛的兼容性,即使在今天,使用 int 80h 而不是 sysenter 仍然是有意义的。如果你使用的是 64 位版本的 Ubuntu,那么 sysenter/sysexit 会被到处使用。

编辑:实际上使用的系统调用机制是由内核在启动时决定的,而不是由 glibc 决定的。 This page(第 4.6 节)解释了它是如何工作的。在您的情况下,恰好由 VMware 模拟的硬件被内核认为使用 int 80h 而不是 sysenter 更有效。您必须调试内核才能弄清楚它是如何做出该决定的。

【讨论】:

  • 非常合理!我猜,兼容性是 Ubuntu 版本最关心的问题之一。
  • 但是正如Peter所指出的,内核已经使用vsyscall解决了兼容性问题,无论处理器是否有sysenter指令,那么为什么在Ubuntu中配置的glibc不直接使用vsyscall呢?
  • 编辑了我的帖子,为您的上一个问题提供了可能的答案。
  • 我系统中的Glibc直接使用int 80h,忽略vsyscall页面。实际上,没有新“编辑”的答案更合理。还是谢谢。
  • 后来发现在Ubuntu 8.04的原生环境glibc“调用*%gs:10h”,然后调用sysenter(当然处理器不是老款,所以支持sysenter)。所以原来是 VMware 影响了 ubuntu 的安装,并且 glibc 使用了 int 80h 进行系统调用。
【解决方案2】:

什么指令(int80 或 sysenter)总是由客户操作系统本身决定,正如您从 linux 内核源代码中看到的那样 - 这完全取决于 VMware 提供给它的硬件。

查看文件arch/x86/vdso/vdso32-setup.c(linux内核源码):

   if (vdso32_syscall()) {
            vsyscall = &vdso32_syscall_start;
            vsyscall_len = &vdso32_syscall_end - &vdso32_syscall_start;
    } else if (vdso32_sysenter()){
            vsyscall = &vdso32_sysenter_start;
            vsyscall_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
    } else {
            vsyscall = &vdso32_int80_start;
            vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
    }

从上面你可以看到,只有当 sysenter 特征检测失败时才决定使用 int80。而这一功能又通过 VMWare 的仿真引擎呈现给来宾。也许如果您使用了最新版本的 VMware 以及一些现代硬件,VMware 应该为客人提供更现代的操作系统。

【讨论】:

  • 确实如此。内核确实检测到 sysenter/syscall 的可用性以生成 vsyscall。例如,在我的例子中,vsyscall 页面包含用于处理系统调用的 sysenter 指令。但是,glibc 直接调用 int 80h 而不是 call %gs:10h(vsyscall 的入口),这意味着 glibc 忽略了 vsyscall。
猜你喜欢
  • 2013-06-16
  • 2011-01-09
  • 2016-03-27
  • 2014-09-28
  • 2012-08-30
  • 2013-11-14
  • 2017-03-20
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多