为啥 32 位内核可以运行 64 位二进制文​​件?

Posted

技术标签:

【中文标题】为啥 32 位内核可以运行 64 位二进制文​​件?【英文标题】:How come a 32 bit kernel can run a 64 bit binary?为什么 32 位内核可以运行 64 位二进制文​​件? 【发布时间】:2010-09-08 04:11:11 【问题描述】:

在我的 OS X 机器上,内核是 32 位二进制文​​件,但它可以运行 64 位二进制文​​件。 这是如何工作的?

cristi:~ diciu$ 文件 ./a.out ./a.out:Mach-O 64 位可执行 x86_64 cristi:~ diciu$ 文件 /mach_kernel /mach_kernel:具有 2 个架构的 Mach-O 通用二进制文件 /mach_kernel(用于架构 i386):Mach-O 可执行 i386 /mach_kernel(用于架构 ppc):Mach-O 可执行 ppc 克里斯蒂:~ diciu$ ./a.out 克里斯蒂:~ diciu$ echo $? 1

【问题讨论】:

How does OSX run 64bit Binaries while running on a 32bit Kernel? 【参考方案1】:

一个 ELF32 文件可以包含 64 位指令并以 64 位模式运行。它唯一拥有的是标题和符号的组织是 32 位格式。符号表偏移量为 32 位。符号表条目是 32 位宽等。同时包含 64 位代码和 32 位代码的文件可以将自己暴露为 32 位 ELF 文件,其中它使用 64 位寄存器进行内部计算。 mach_kernel 就是这样一种可执行文件。它获得的好处是 32 位驱动程序 ELF 可以链接到它。如果它负责将位于 4GB 以下的指针传递给其他链接的 ELF 二进制文件,它将正常工作。

【讨论】:

【参考方案2】:

请注意,并非所有 32 位内核都能够运行 64 位进程。 Windows 肯定没有这个属性,我从来没有在 Linux 上看到过。

【讨论】:

主题行没有,但osx标签有。 知道了——我错过了。希望这个比较对其他在这个问题上的绊脚石有用。我会稍微修改一下文本。 Linus 永远不会允许这个功能进入 Linux,他甚至对 PAE 大发雷霆。【参考方案3】:

能够加载和运行 64 位二进制文​​件的 32 位内核必须有一些 64 位代码来处理内存映射、程序加载和一些其他 64 位问题。

但是,调度程序和许多其他操作系统操作不需要在 64 位模式下工作以处理其他问题 - 它会根据需要将处理器切换到 32 位模式并切换回来以处理驱动程序、任务、内存分配和映射、中断等

事实上,操作系统所做的大多数事情在 64 位运行时不一定会更快地运行 - 操作系统不是重型数据处理器,而那些部分(流、磁盘 I/O 等)很可能会转换为 64 位(无论如何都是操作系统的插件)。

但如果是 64 位,裸内核本身可能不会更快地进行任务切换等。

当大多数人仍在运行 32 位应用程序时尤其如此,因此并不总是需要模式切换,即使这是一个低开销的操作,但确实需要一些时间。

-亚当

【讨论】:

【参考方案4】:

CPU 可以在陷入内核上下文时从 64 位执行模式切换到 32 位,并且仍然可以构建 32 位内核来理解从 64 位用户空间应用程序传入的结构。

MacOS X 内核无论如何都不会直接从用户应用程序中取消引用指针,因为它驻留在自己的独立地址空间中。例如,ioctl 调用中的用户空间指针必须首先解析为其物理地址,然后在内核地址空间中创建一个新的虚拟地址。 ioctl 中的指针是 64 位还是 32 位并不重要,无论哪种情况,内核都不会直接取消引用它。

因此混合 32 位内核和 64 位二进制文​​件可以工作,反之亦然。您不能做的是将 32 位库与 64 位应用程序混合使用,因为它们之间传递的指针将被截断。 MacOS X 在每个版本中都提供了更多的 32 位和 64 位版本的框架。

【讨论】:

这是否意味着 32 位内核必须知道 64 位指针,因为它必须转换它?【参考方案5】:

内核为 64 位只会带来内核扩展(即通常是驱动程序)可以是 64 位的有效优势。事实上,您需要拥有所有 64 位内核扩展,或者(就像现在一样)所有 32 位内核扩展;它们需要在运行内核的体系结构中是原生的。

【讨论】:

只要有便宜的硬件需要便宜的第三方驱动程序,不要指望很快就会出现 64 位内核 :-) 64位Windows需要64位驱动,内核运行在64位模式。您不能在 64 位 Windows 上运行 32 位驱动程序。上面的示例是 OS X,它没有单独的 32 位和 64 位版本(只是能够在带有 32 位内核的 x64 上运行 64 位应用程序)。 NT 和 OSX 都运行在微内核上,可以在消息传递时进行 3264 位模式切换。但它会减慢速度。【参考方案6】:

运行二进制文件的不是内核。这是处理器。

二进制文件确实调用了库函数,并且这些函数需要是 64 位的。而如果他们需要进行系统调用,他们有责任应对自己是64位的,但内核只有32位的事实。

但这不是你必须担心的事情。

【讨论】:

以上是关于为啥 32 位内核可以运行 64 位二进制文​​件?的主要内容,如果未能解决你的问题,请参考以下文章

在运行 64 位 linux 的 Armv8 (aarch64) 上编译并运行 32 位二进制文​​件

在 64 位系统上组装 32 位二进制文​​件(GNU 工具链)

gcc:在 32 位平台上编译 64 位二进制文​​件

如何使用 npm 在 64 位系统上构建 32 位二进制文​​件?

Objcopy 获取目标文件 64 位二进制文​​件

在 64 位 Debian wheezy 多架构主机上编译使用 ssl 的 32 位二进制文​​件