OSX在32位内核上运行时如何运行64位Binaries?


6

我最近发现,即使加载了x86内核,Mac OS X实际上也可以运行64位(x64)应用程序。这让我第一次感到震惊。

但是后来我意识到,如果系统启动并在与x64兼容的CPU上运行,那无论使用什么内核来管理进程,都无法运行x64应用程序,那真的很奇怪。真的那么难吗?只需将该死的应用程序加载到内存中,然后将CPU操作指针设置为第一个字节即可,就像馅饼一样容易!

如我所能想象的那样,实现此目标的唯一且唯一的障碍是某种“可执行标头”。不幸的是,我对Windows体系结构和二进制结构不太满意,因此在此需要更多说明。

事实上类UNIX操作系统二进制头标准的ELF有它的兄弟ELF64,这(如文档这里描述)没有与ELF32多大差别,但即使32位内核是无法运行的x64代码。是的,该程序可能已链接到x64库,并且可以想象我们刚刚将它们复制并粘贴到/ usr / lib64文件夹中。但是我很确定这无济于事,为什么呢?

最后,Mac OS X内核有什么特别之处,而不必担心所使用的程序指令集?Mac OS X是否具有某种通用性并且适用于两个内核可执行文件头,因此它可以将应用程序加载到内存中并对CPU说“从此处立即执行,我不介意那代表什么”?

PS:我真的很想在哪里放置这个问题:在stackoverflow.com或superuser.com上,并决定放在此处,因为该主题可能是更特定于OS的东西。


是什么让您认为OSX在32位Darwin内核上运行时将运行64位二进制文​​件?你看见什么了?
James T Snell

因为我非常确定我正在运行x64内核,所以我安装的唯一软件是x64,并且OS可以很好地运行它们。但是不久前,我在终端中输入了“ uname -a”,感到很惊讶。此外,维基百科证实了这一点- en.wikipedia.org/wiki/X86-64#Mac_OS_X
pechenie

维基百科和你们俩都可能会误会。运行64位操作系统并不意味着您所有的二进制文件都是32位。这意味着您的内核和硬件体系结构可以支持64位二进制文​​件。您的名誉回报是什么?
James T Snell

另外,我不明白您的问题标题。您能改一下吗?
James T Snell

这不是一个错误,如果可以的话,您可以尝试一下。我正在运行x86内核,而不是x64,因此它仍然能够运行x64软件。我现在已经切换到x64_86体系结构,但是uname -a在x86内核下的输出可能是这样的:Darwin MacMini.local 11.1.0 Darwin Kernel Version 11.1.0: Tue Jul 26 16:07:11 PDT 2011; root:xnu-1699.22.81~1/RELEASE_i386 i386
pechenie 2011年

Answers:


5

真正的问题是为什么某些其他操作系统无法在32位内核上运行64位二进制文​​件。没有根本原因无法实现。底层处理器体系结构同时支持64位指令集(amd64 aka x86-64)和32位指令集(i386),并且对两者一起使用没有限制(特别是没有与“ 32位模式”分开的“ 64位模式”;只有一个长模式,它允许来自i386和“本机” amd64集的指令)。

在32位内核上运行64位应用程序确实需要在内核内部做更多的工作,因为它必须管理指向用户空间的64位指针以及指向内核空间的32位指针。大多数(如果不是全部)在内核中传递的指针,要么被称为内核空间,要么被称为用户空间,因此,如果它们的大小不同,这不是问题。最主要的困难是无法使用通用指针类型,该类型具有用于进程内存,内核内存和各种硬件(包括RAM)使用的内存的值的单独范围,但是在最近的32位内核中无法实现无论如何,在PC级硬件上(如果您拥有4GB或更多的RAM,或者要映射2GB的RAM,2GB的处理空间以及内核内存等,则需要能够映射32位以上的内存)

根据您引用的Wikipedia文章,OSX能够在具有64位内核之前在amd64处理器上运行amd64进程。无论内核是32位还是64位(均可用),Solaris也会在amd64处理器上无差别地混合i386和amd64可执行文件。

其他操作系统可以在(64位)amd64内核上运行i386进程,但不能在32位内核上运行amd64进程,例如Linux,FreeBSD,NetBSD和Windows。其他操作系统将amd64和i386视为完全不同的体系结构,例如OpenBSD。


AIUI指针在OS X中不是问题,因为无论如何它们不会在内核和用户空间之间传递。即使在32位内核下运行32位进程,该进程也可以定义最多4GB的虚拟内存空间,内核也最多可以定义4GB,并且两者不会重叠。如果将指针从用户空间传递到内核,那将毫无意义,因为内核空间中的该地址存在完全不同的东西。
Gordon Davisson

如果您查看源代码,则可以看到它是如何完成的。在32位OS X上,内核未映射到用户地址空间,因此它们都具有完全独立的32位地址空间。传递的所有数据无论如何都将被复制或重新映射。代价是TLB缓存未命中。
russbishop 2014年

问题是当32位模式无法访问前64位以及8个高位寄存器时,CPU如何存储上下文?
phuclv

1
@LưuVĩnhPhúc您只需要一点点64位代码,即可保存和恢复寄存器。据我所知,这在x86-64上是可能的(例如Solaris就是这样做的)。如果不更改特权就无法混合使用64位和32位指令,这确实是一个问题。
吉尔斯

4

我对x86_64体系结构不够熟悉,无法提供详细信息,但是本质上发生的是,CPU在内核和用户空间之间进行上下文切换的一部分在64位模式和兼容性(32位)模式之间切换程序。这与在64位内核下运行32位程序几乎是一样的,只是相反。

顺便说一句,OS X不使用ELF二进制格式,它使用Mach-O二进制文件。Mach-O格式允许多体系结构(“通用”)二进制文件,因此可以以32位和64位(以及PPC和PPC64等)提供程序(就此而言,是内核)。选择在加载时加载哪个版本(以及以哪种模式运行)。您可以file在二进制文件上使用该命令以查看其格式。例如,以下是OS X v10.5附带的Chess应用程序:

$ file Applications/Chess.app/Contents/MacOS/Chess 
Applications/Chess.app/Contents/MacOS/Chess: Mach-O universal binary with 4 architectures
Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc): Mach-O executable ppc
Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc64):   Mach-O 64-bit executable ppc64
Applications/Chess.app/Contents/MacOS/Chess (for architecture i386):    Mach-O executable i386
Applications/Chess.app/Contents/MacOS/Chess (for architecture x86_64):  Mach-O 64-bit executable x86_64

并向那些怀疑这是否可能的人提供注释:OS X支持从v10.4开始的64位程序(具有有限的API支持),但是直到v10.6才包括64位内核(即使这样,大多数型号默认情况下,内核以32位模式运行)。有关详细信息,请参见Apple的64位过渡指南。我是从运行10.6且具有32位内核的MacBook Pro上发布此消息的(此特定型号不支持64位),但是根据Activity Monitor的说法,唯一不在64位模式下运行的进程是kernel_task。


4

Macs支持在32位内核之上运行64位应用程序,因为多阶段计划可以做到这一点:

  1. Mac应用程序在“捆绑包”中以“胖二进制文件”的形式提供,它允许将64位/ 32位和Intel / PPC的所有四个组合作为单个安装的一部分,这可以像拖放一样简单。操作系统运行适当的操作系统。
  2. Mac运行32位内核时,使用PAE访问超过4GB的RAM。Windows不允许在非服务器版本上使用PAE,这是因为驱动程序存在兼容性问题,而驱动程序存在很多此类问题,包括第三方驱动程序。
  3. Tiger添加了一个64位ABI(应用程序二进制接口)以在32位内核之上运行64位代码,并为“控制台”添加了64位版本的低级API(应用程序编程接口)(非GUI)应用。
  4. Leopard为GUI应用程序添加了64位Cocoa(但没有添加64位Carbon)。
  5. Snow Leopard添加了64位内核,这是仅某些高端机型的默认设置。
  6. Lion需要64位CPU,但仍包括32位内核。例如,一台旧的Mac使用64位CPU,而GPU仅具有32位驱动程序,则必须运行32位内核。

因此,OS X尽快支持64位应用程序,并且由于驱动程序的原因,将尽可能长时间地继续运行32位内核。(仅当尝试管理大量RAM时,内核的位才成为一个因素-页面表也占用了内存-切换到64位内核会带来一些性能优势。)但是,Apple当然不愿意放弃东西。

真正的问题是,为什么Windows和Linux不会做同样的事情。对于Windows,请考虑他们对Win64的首次尝试是使用Itanium,这是完全不同的。但是最终的答案可能归结为过去几十年来通常所拥有的:与一堆做得不太正确的第三方程序的兼容性:

OS X的64位实现与Windows显着不同,Windows将其32位和64位版本视为存储在不同安装媒体上的两个不同的操作系统。这样做主要是为了维持Windows与旧应用程序的兼容性-移动或重命名System32文件夹之类的东西会破坏预期该文件存在的程序-结果这两个文件被分开,以至于根本没有升级32位Windows和64位Windows之间的路径。因此,由于Windows应用程序和驱动程序通常具有不同的32位和64位版本,因此Windows向64位的过渡比较困难,用户也可以看到。

Mac端Windows端都有许多有关64位转换的背景信息。(这些链接是每个系列文章的最后一部分;请确保回到每个文章的开头。)

我不知道Linux的故事是什么,但是可以想象Linus对它有强烈的看法。


1
从Linux方面来看:内核在amd64出现之前就已经支持32位和64位体系结构。在32位内核上运行64位进程至少在代码的与体系结构相关的部分中需要进行一些重新设计。在amd64内核上运行i386二进制文件已经足够了,但是在(更复杂的)另一端则没有,因为在该方向上并没有真正令人振奋的用例(如果您要运行64位进程,则没有理由不运行64位内核)。
吉尔斯

非常感谢您的解释,我还不能投票(信誉不够),我也不能接受两个答案,但是您和Gilles都对我更清楚了!
pechenie 2011年

0

我已经意识到,如果系统在x64兼容CPU上启动并运行,那实在是很奇怪的,无论使用什么内核管理进程,都无法运行x64应用程序。真的那么难吗?只需将该死的应用程序加载到内存中,然后将CPU操作指针设置为第一个字节即可,就像馅饼一样容易!

您缺少重要的部分。应用程序对操作系统提供的功能和服务进行API调用。如果64位应用程序将64位指针发送到32位操作系统,则情况应该会崩溃。

我怀疑为了使任何一种方法都能令人满意地工作,操作系统必须重载该功能并提供每个功能的64位和32位版本。对于每个内核,“关闭”功能(32位内核上的64位功能,64位内核上的32位功能)将只是一个存根,它将调用转换为32位安全,然后重新调用本机函数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.