【问题标题】:Are Linux programs as portable as Windows programs? [closed]Linux 程序与 Windows 程序一样可移植吗? [关闭]
【发布时间】:2015-08-16 19:08:25
【问题描述】:

也许这是一个愚蠢的问题,但它是从人们四处交谈中学到的其中一个,如果专业人士正确描述了这种情况,我会很高兴。

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

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

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

【问题讨论】:

标签: c++ c linux windows portability


【解决方案1】:

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

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

不幸的是,Linux 生态系统并没有硬性保证不同发行版之间或不同版本之间的二进制兼容性。但在实践中,存在相当数量的兼容性。特别是,单独的发行版可能会提供更强的兼容性保证。并且在特定发行版的一次安装上编译的二进制文件可以在该版本的任何安装上使用,只要它们具有相同的体系结构——Linux 上的大多数包管理器都使用带有此类预编译二进制文件的包。但请注意,这些包通常是在具有严格控制依赖关系的参考安装上编译的。

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

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

【讨论】:

    【解决方案2】:

    我假设您的问题是关于 Linux 版本之间的应用程序可移植性。

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

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

    2. 架构。 (例如,系统没有 32 位 libc,在 ARM 上你关心软/硬浮点之类的东西,应用程序可能使用 SSE2/AVX2 但内核不知道如何在上下文切换后保留寄存器)

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

    一些极不可能的可能性:

    1. 可执行格式。 (例如,您的应用是 ELF,但系统只知道 a.out)
    2. 资源限制。 (例如,没有 PAE 的 32 位内核无法映射您的 40GB 文件)

    这只是基础。我什至不想开始讨论使用 Xorg 或任何接近 OpenGL 的问题。

    【讨论】:

    • 如果您不介意,我有兴趣简要介绍一下 linux 中的 OpenGL 状态?
    • @Serthy:似乎不是这个问题的一部分......
    【解决方案3】:

    在 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 完全不同的代码库。有时是因为在更高版本的操作系统中修复了错误。所以你永远无法确定。基本上,您必须在部署的每个新平台上进行测试。

    【讨论】:

    • 感谢您的回答。当然我不是说在linux上编译然后在windows上运行。我知道处理器映射是不同的。现在我有我在 Windows Vista 上编译的程序,我仍然可以在 Windows 10 上运行它们,没有任何问题,如果这就是你的意思的话。所以我的问题是,决定这一点的标准是什么?我总是将我的程序编译为静态的。够了吗?我会得到什么样的错误?
    • 这不完全是关于“处理器映射”,而是关于程序如何与操作系统/其他库对话。如果 microsoft 更改了程序应该用来与 windows 对话的 API,或者更改了这些 api 函数的工作方式不兼容,那么当您尝试在新版本的 windows 上运行它时,您的程序可能会突然中断或崩溃而没有任何解释。
    猜你喜欢
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 2013-12-08
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多