65.9K
CodeProject 正在变化。 阅读更多。
Home

处理 .NET 中的 32 位、64 位和AnyCPU 编译选项

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (15投票s)

2016年12月12日

CPOL

4分钟阅读

viewsIcon

33847

您是否曾经想过为什么 Visual Studio IDE 提供了 3 种编译选项 - x86、x64 和 Any CPU?在这篇文章中,我希望对此有所阐述。

您是否曾想过 Visual Studio IDE 为什么提供 3 种编译选项 - x86x64Any CPU
虽然大多数人都知道这些选项,但很多人仍然不清楚这些选项的意义(包括我早期职业生涯中也是如此)。因此,在这篇文章中,我希望能够消除一些疑虑。

Windows 操作系统经历了多年的发展,从最初的 **16 位** 操作系统,过渡到 **32 位**(x86),再到最近的 **64 位**(x64)。

为什么要在 32 位之上使用 64 位操作系统?

要理解这一点,让我们先了解 **32 位** 和 **64 位** CPU 的能力。

  • 32 位 CPU

    • 地址指针大小为 **32 位** -> 可以访问 **2^32 (4,294,967,296)** 个离散地址。
    • 这允许程序在内存中创建高达 **4 GB** 大小的数据结构。
  • 64 位 CPU

    • 地址指针大小为 **64 位** -> 可以访问 **2^64 (18,446,744,073,709,551,616)** 个离散地址。
    • 这允许程序在内存中创建高达 **16 EB**(艾字节)大小的数据结构。
  • 主要优势(64 位相对于 32 位)

    • 与 **32 位** CPU 相比,**64 位** CPU 上的进程可以处理更多的数据集(仅受限于物理内存)。
    • 一个 **64 位** 整数进行算术或逻辑运算,使用 **64 位** 类型(如 **C#** 的 long)比使用两个 **32 位** 操作实现的运算更快。
  • 总而言之,在所有实际应用场景下……

    • 使用大量内存的应用程序,如图像和视频编辑软件、3D 渲染工具和视频游戏,将能更好地利用 **64 位架构** 和操作系统,特别是当机器拥有 **8 GB** 甚至 **16 GB** 的 **RAM**,并且可以分配给需要它的应用程序时。

理解 32 位、64 位和 Any CPU 编译的 PE 文件行为

  • 在 32 位机器上

    • **Any CPU**:作为 **32 位** 进程运行,可以加载 **Any CPU** 和 x86 程序集,如果尝试加载 x64 程序集,将收到 BadImageFormatException
    • **Any CPU-32 位优先(默认)**:与 **Any CPU** 相同。
    • **x86**:与 **Any CPU** 相同。
    • **x64**:始终收到 BadImageFormatException
  • 在 64 位机器上

    • **Any CPU**:作为 **64 位** 进程运行,可以加载 **Any CPU** 和 x64 程序集,如果尝试加载 x86 程序集,将收到 BadImageFormatException
    • **Any CPU-32 位优先(默认)**:作为 **32 位** 进程运行,可以加载 **Any CPU** 和 x86 程序集,如果尝试加载 x64 程序集,将收到 BadImageFormatException
    • **x86**:作为 **32 位** 进程运行,可以加载 **Any CPU** 和 x86 程序集,如果尝试加载 x64 程序集,将收到 BadImageFormatException
    • **x64**:与 **Any CPU** 相同。

Any CPU-32 位优先

这是从 **.NET 4.5** 和 **Visual Studio 11** 开始引入的新选项。它是 **Any CPU** 的一个新子类型,也是 **IDE** 中的默认编译选项。

您可以在项目属性中检查此项,如下图所示…

Visual Studio project properties default compilation option

32 位 PE 在 64 位架构上如何工作?

  • 通常,只有 **32 位** PE 可以加载到 **32 位** 进程中,只有 **64 位** PE 可以加载到 **64 位** 进程中。
  • 当 **32 位** PE 在 **64 位** 操作系统上运行时,它会在 **“WOW”**(**Windows-32 on Windows-64**)中运行,为进程呈现一个 **32 位** 操作系统的 *假象*。

为什么引入 Any CPU 编译选项?

  • 在 **64 位** Windows 操作系统出现之前,只有 **32 位** PE(当然,我们在此讨论中不考虑 **16 位** 操作系统),因此在编译时,这些 PE 被标记为 **32 位**,没有歧义。
  • 随着 **64 位** Windows 操作系统的引入,必须做出一个决定——默认情况下,二进制文件应该被标记为 **32 位** 还是 **64 位**?
  • 从技术上讲,托管二进制文件没有 *硬 CPU 依赖性* - 它们可以是 **32 位** 或 **64 位**。
  • 但是,需要一种方法来让 **32 位** 和 **64 位** 进程重用 .NET 库。为此,**OS 加载器** 的支持得到了扩展,以支持 **体系结构中立** 的 PE 文件 **(Any CPU)**。
  • 对于 **Any CPU** PE,**OS 加载器** 决定如何初始化进程。在 **64 位** 操作系统上,它们作为 **64 位** 进程运行;在 **32 位** 操作系统上,它们作为 **32 位** 进程运行。

希望这篇文章有助于澄清一些事情!!
我将在未来的文章中介绍如何识别 PE 的 **体系结构亲和性**。

缩写

  • **PE**:进程可执行文件(EXEs 和 DLLs)

参考文献

文章 处理 .NET 中的 32 位、64 位和 Any CPU 编译选项 首次出现在 Sundeep Kamath 的博客

© . All rights reserved.