Linux程序是否像Windows程序一样可移植?

时间:2015-08-16 19:08:26

标签: c++ c linux windows portability

也许这是一个愚蠢的问题,但是其中一个问题来自人们在这里和那里说话,如果专业人士正确地描述了这种情况,我会感到高兴。

谈到标准台式计算机,我发现Windows程序尽可能便携。我可以使用静态库链接编译任何32位软件,然后将该软件放在闪存驱动器上,它可以在世界上任何32位或64位的计算机上运行。我有超过10年的程序,他们仍然没有一个问题。

现在我也在编写Linux程序,但在执行linux程序时我并没有考虑到这一点。我总是认为它应该在每个必须使用程序的系统中编译。一位同事告诉我,两台Linux计算机盲目地在两台计算机上运行相同的软件是错误的。但是......我在Windows上使用静态可执行文件执行此操作。我能在linux 2中做到这一点吗?

总结一下我的问题:在Linux上创建便携式软件的限制是什么,就像人们在Windows上一样?当然,假设目标计算机除了一些任意版本的glibc之外根本没有库。所有库在我脑海中的模型中是静态的。

3 个答案:

答案 0 :(得分:11)

在Linux世界中,二进制兼容性并不像源兼容性那样重要,因为Linux周围的大部分生态系统都是开源的。即使二进制兼容性中断,您仍然可以在再次编译它们之后运行旧程序。在Windows生态系统中,这是不可能的:大多数软件都是闭源的,因此用户将依赖软件供应商来更新软件以获得新的操作系统版本。由于这基本上从未发生过,因此Windows非常重视维护二进制级别的反向计算,以至于20年前的二进制文件通常仍然可以运行。

Linux有一个名为Linux Standard Base(LSB)的规范,它试图为源兼容性提供稳定的应用程序编程接口(API),并为二进制兼容性提供更有限的应用程序二进制接口(ABI)。它基于POSIX和单Unix规范。但是,大多数Linux发行版都没有完全实现LSB。与Red Hat相关的发行组似乎比Debian和Ubuntu相关的发行版更紧密地遵循它。

所以遗憾的是,Linux生态系统并没有针对不同发行版之间或不同版本之间的二进制兼容性提供硬性保证。但在实践中,仍然存在合理的兼容性。特别是,单个发行版可能提供更强的兼容性保证。在一个特定版本的安装上编译的二进制文件可用于该版本的任何安装,前提是它们具有相同的体系结构 - Linux上的大多数软件包管理器都使用具有此类预编译二进制文件的软件包。但请注意,这些包通常是在具有严格控制依赖性的引用安装上编译的。

在某些情况下,可以跨越体系结构,可执行格式和OS ABI的边界。例如。 WINE接口层有一个Windows'的实现。 “可移植可执行”格式,并重新实现了Windows ABI的重要部分,导致Windows→Linux二进制兼容性有限。架构边界只能通过使用仿真器来交叉(例如,即使使用相同的操作系统版本,您也无法在AMD64系统上使用为SPARC编译的软件)。

AMD64架构上x86二进制文件的兼容性是一种特殊情况。 AMD64指令集专门设计为向后兼容x64(这就是它如此成功的原因)。操作系统仍然需要为在AMD64系统(64位)上运行x86二进制文件(具有32位指针)提供特殊的内核级支持,但所有严肃的操作系统都提供这种支持。

答案 1 :(得分:7)

我认为你的问题是Linux版本之间的应用程序可移植性。

Linux版本之间存在不同类型的API / ABI不兼容性。最常见的可以影响静态可执行文件的是:

  1. libc版本。 (例如你的应用程序依赖于glibc特定的功能,但主机有一个非常旧的版本或有另一个C库(newlib,仿生等))

  2. <强>建筑即可。 (例如系统没有32位libc,在ARM上你关心像软/硬浮点的东西,app可能会使用SSE2 / AVX2但是内核不知道如何在上下文切换后保留寄存器)

  3. 系统调用/硬件支持。这通常是新内核API(inotify / old dnotify)之类的东西。旧内核也不知道IPv6,USB3.0。将来可能会删除一些旧的内核API。

  4. 一些极不可能的可能性:

    1. 可执行格式。 (例如,您的应用程序是ELF,但系统只知道a.out)
    2. 资源限制。 (例如没有PAE的32位内核无法mmap你的40GB文件)
    3. 这只是基础知识。我甚至不想开始使用Xorg或任何接近OpenGL的问题。

答案 2 :(得分:1)

在Windows平台上使用C编译器编译的程序依赖于Windows平台。然后,您可以尝试在另一台Windows计算机上运行此程序,它可能运行正常。但Linux程序可以说完全相同。

您将无法将该程序复制到unix计算机上并运行它。

根据您编写程序的方式,很可能重新编译在MAC或Linux PC上的Windows机器上开发的程序源。但反过来也是如此。

例如,这个C程序:

#include <stdio.h>

int main() {
  printf("Hello World!");
}
如果为每个平台重新编译,

将在Windows,MAC和Linux以及许多平台上运行。

Windows操作系统之间存在差异,这意味着在Windows 7上编写的程序无法在Windows 8上运行。这取决于程序。

关于静态与动态链接的问题,那么静态链接可以使您的程序更可能在具有相同操作系统的系统上运行,因为函数库当然已经存在于可执行文件中。但静态链接不会使您的程序可移植到不同的操作系统。 Windows上的C运行时库对于在unix上运行的程序没有用处。系统的界面非常不同。

我写了一个程序,最初在Windows 98上进行语音处理,后来我将它移植到Windows NT4和更高版本的Windows 2000.我不得不更改每个新操作系统的代码。这与图书馆无关。其中一些原因是因为该功能的实现在不同的操作系统中发生了变化。而Windows 9X是与Windows NT完全不同的代码库。有时这是因为在后续版本的操作系统中修复了错误。所以你永远不能确定。基本上,您必须在部署的每个新平台上进行测试。