21

64 位库可以在 32 位应用程序中工作吗?例如,我的应用程序 GUI 使用 32 位 Qt。而我的业务核心是一个 64 位的库。操作系统是 64 位的。他们可以一起工作吗?如何工作?谢谢。

4

4 回答 4

23

简而言之:您不能将 32 位应用程序链接到 64 位库。

您可以在 64 位操作系统(至少所有流行的 32/64 位处理器,如 AMD、Intel 和 Sparc)上使用 32 位共享库来运行 32 位应用程序。但这不涉及任何库。

更长的答案:我参与了一些为 x86 设计 64 位 Linux 内核的团队(在郊区)。有简短的(与整个项目相比,讨论持续了好几个小时)关于如何在技术上完成这项工作的一些讨论。对此的简短总结是,在 64 位中有一些寄存器在 32 位中不可用。还有内存地址和寄存器中额外的 32 位的问题。假设库本身“知道”它是一个 32 位兼容库,所有这些都可以解决。但是我们基本上有一个 64 位库,它被写成一个 32 位库,我们有点迷失了方向。

“更多寄存器”可能不适用于某些处理器,但更大的寄存器地址/位范围肯定适用于所有 32 位和 64 位兼容处理器。而且我不知道有任何单个处理器允许 32 位代码调用 64 位共享库或静态库。除非专门编写代码来解决这个问题,否则它是行不通的,这违背了拥有通用 64 位库来支持 32 位应用程序的目的。

编辑:

以上讨论了链接一个可执行单元,例如可执行文件、共享库或静态库。那必须是所有“一位”,无论是 32 还是 64 - 没有混合。

当一个进程与另一个进程通信时(例如,一个显示非 GUI 进程状态的 GUI 应用程序),只要两个进程使用相同的协议 [通常,IPC 无论如何都不允许传递指针,所以32-/64 位转换不是一个大问题],您可以拥有一个 32 位进程和另一个 64 位进程。

于 2013-04-12T12:57:10.130 回答
7

是的,但这是一个大麻烦。

首先,内核不同于库。通常,库在进程的虚拟地址空间中可见;它与您自己的代码共享地址空间。调用库例程只是一个子例程调用。

相反,要向内核请求服务,您的进程会执行一条特殊指令来生成陷阱。这个陷阱会导致处理器做一些特殊的事情,包括将进程的寄存器和其他状态保存在内存中(或在您通常无法访问的特殊处理器寄存器中),更改处理器中的各种模式以使其适合内核,以及更改程序计数器以指向内核的指令。然后内核运行。此时,内核可能在 64 位模式下运行,而您的进程在 32 位模式下运行。但是,内核被设计为意识到这些差异。当您的内核检查您的进程以查看您的请求时,它会查找知道您的进程在 32 位模式下运行的信息和数据结构。

当然,这假定您使用的 64 位内核支持 32 位进程。

通常,当您调用一个库时,您希望它与您的代码具有相同的模式,因为正常的库调用只是一个子程序调用;它不会产生陷阱,也不会改变处理器模式。如果迫切需要从 32 位进程调用 64 位库中的例程,那么您可以创建一个帮助程序 64 位进程。您的 32 位进程将打包一个库调用请求,并通过某种形式的进程间通信将该请求发送到 64 位助手进程。该辅助进程将调用库例程并将结果发回。

自然,这会为每个库调用增加大量开销,因此只有在非常需要且没有更好的选择时才需要这样做。

于 2013-04-12T13:06:38.800 回答
2

我正在开发一个可以做到这一点的应用程序。应用程序核心是 x64(并使用 Qt),但它必须与一些设备通信,为此我只有制造商的 32 位库。我实现它的方式是有两个应用程序 64 位用于核心和 GUI,32 位控制设备并使用 QSharedMemory 与主要应用程序通信。这两个应用程序都基于 Qt(对应 64 位和 32 位)。

于 2013-04-12T13:28:01.163 回答
1

如果您在 Windows 上运行,那么为 32b 编译的应用程序可以在 Windows 64b 主机系统上运行:看看64b Windows 中内置的WOW64子系统。

话虽如此,您不能将为 32b 编译的代码与为 64b 编译的代码混合使用。这意味着为 32b 构建的库不能与 64b 代码链接,反之亦然。(不同的调用约定,堆栈框架布局,展开除外,...)

于 2013-04-12T12:55:14.057 回答