6

起初这听起来像是一个愚蠢的问题,但请耐心等待。

众所周知,一种 CPU 架构的二进制文件不会在其他架构上运行。例如,不可能在 sparc64 芯片上运行 x86 二进制文件(没有某种兼容层)。指令集是不同的,所以很明显这是行不通的。

但是,当二进制文件用于同一个 CPU,但用于不同的操作系统时,代码的哪一部分会阻止执行。例如,在 x86 Linux 机器上运行 x86 Solaris 二进制文件。我假设存在某种与运行时链接器或进程调度器相关的平台特定存根?

我很想知道。谢谢。

4

8 回答 8

12

有很多原因。主要的,按“与金属的距离”排序的是:

  1. 操作系统对于可执行文件可能具有不同的二进制格式。在这种情况下,您将无法首先加载二进制文件。
  2. 程序可以使用另一种方法来表明他们希望进行系统调用(例如 INT21 与 INT80)。
  3. 该程序可能依赖于其他操作系统中不存在的系统调用(例如 dlopen())
  4. 该程序可能依赖于其他操作系统上不存在的标准库。
  5. 该程序可能依赖于其他操作系统上不可用的其他库。

当然,在意想不到的环境中运行的程序可能会以多种方式严重失败。

于 2009-05-31T15:37:26.693 回答
5

有四个问题:

  1. 不同的操作系统以不同的方式打包它们的二进制可执行文件(例如 Linux ELF 与 Windows 格式);
  2. 不同 CPU 架构上的不同指令集;
  3. 不同的操作系统有不同的系统调用(例如 Win32 中的 CreateProcess() 与 Linux/Unix 中的 fork());
  4. 路径、合法字符、目录分隔符等差异。

假定两者都存在非系统库,否则这是另一个区别。

于 2009-05-31T15:39:42.840 回答
3

主要是API。例如,Win32 API 在 Linux 上并不真正可用。不过,有可能解决这个问题,请参阅Wine。可执行格式也可能不同(ELF/PE),但可以很容易地修复(Wine 可以做到这一点;它允许 PE 可执行文件在 Linux 上执行)。

此外,您的 Solaris 和 Linux 可执行文件混合示例将相当容易实现,因为操作系统非常相似(ELF 表示可执行格式、POSIX API、X 窗口系统等)。FreeBSD 已经可以运行 Linux 可执行文件。这种情况不常见的原因很简单,就是对它的需求不多。Windows 程序比 *NIX 程序多得多,因此创建了 Wine。Linux 程序比 FreeBSD 程序多得多,因此 FreeBSD 实现了 Linux 兼容层。Solaris 最终也可能实现类似的东西。但是,不要指望相反(Linux 上的 Solaris/BSD 可执行文件),因为没有需求。

于 2009-05-31T15:32:51.813 回答
2

除了二进制格式和其他“打包”功能(这也可能不完全是微不足道的)之外,您还可以在几乎每个代码片段中找到一些后果。像这样的东西

  1. PIC 可能会导致每个全局访问依赖于系统特定的重新加载 GOT 指针的假设,以及额外偏移量的假设。
  2. 许多系统都有特定的 ABI,在寄存器中传递小结构,为对齐目的跳过寄存器,为特殊目的保留寄存器有些有几个(如 ARM EABI 和 OABI)
  3. 线程本地存储相关问题,每个线程实例化的变量与操作系统指定的设施紧密耦合。寄存器选择,偏移量等。
  4. 一些操作系统(最值得注意的是)窗口支持某种格式的异常处理,以允许跨语言甚至跨机器(通过 DCOM)异常处理。
  5. 更高级别的跨程序系统(如 COM,还有 Mac 上的 Objective C 互操作性,或与某个 KDE-gcc 版本组合的兼容性)也可能对 VMT 布局有某些要求。
  6. 一些链接器和格式支持对部分负偏移,有些则不支持。

请注意,这只是一些有趣的东西。它可能不完整,并且并非所有内容都适用。上面的某些点可能会重叠(例如,为 TLS 或 PIC 保留寄存器也是 ABI 更改)

于 2009-06-06T12:48:22.820 回答
1

它是系统特定的库,并不总是可移植的。例如,您不能在 vanilla linux 上使用 win32 窗口 api(是的,我意识到有一些工作场所,例如 wine,它不是最好的例子)。

于 2009-05-31T15:31:51.317 回答
1

系统库和 API。实际的简单代码应该可以工作。这就是为什么像 Wine 这样的层不做任何 CPU 仿真,它们只是重新实现 Windows API。

于 2009-05-31T15:34:20.407 回答
1

除了其他人所说的,可执行文件的实际格式可能有所不同。因此,当操作系统开始加载它时,它不会在文件的正确位置找到它期望的代码、数据段等值。

于 2009-05-31T15:39:42.870 回答
0

正如已经指出的那样,不兼容与可执行文件格式本身的关系不大,与可执行文件引用的库有关。

我相信 linux 实际上与许多不同的可执行格式兼容,尽管我在这里可能是错的

于 2009-05-31T15:35:05.150 回答