什么是64位系统以及64为系统对32位的支持和优缺点

第一讲  什么是64位系统

 

截至本课程编写的时间为止,市场上有两种受欢迎的64位微处理器体系结构:IA64 和Intel64

  1. IA-64是由 Intel 和HP 合作开发的64位微处理机体系结构。Itanium 和Itanium2 微处理机中就是用了这种体系结构。如想了解更多关于IA-64的信息,请查看Itanium
  2. Intel 64 (EM64T / AMD64 / x86-64 / x64)是x86体系的继承,同时保持向后兼容。这种体系结构的名字有不同变型,因而导致了一些疑惑,但是以下这些名字所指的都是同样的事物:x86-64, AA-64, Hammer Architecture, AMD64, Yamhill Technology, EM64T, IA-32e, Intel 64, x64。 想了解更多为什么会有这么多不同的名字,请参看文章

你需要了解到IA-64与Intel64是完全不同、不能相互兼容的微处理机体系结构。在本文的范围内,我们仅讨论在Windows软件开发人员中比较受欢迎的Intel64(x64/AMD64)结构。相对应的,当我们说起Windows 操作系统的时候,我们指的对应Intel64体系的64位操作系统。例如,Windows XP Professional x64 Edition, Windows Vista x64, Windows 7 x64。 Intel64所对应的编程模型,对于基于64位windows开发的程序员来说,简称为Win64

Intel 64 体系结构

以下给出的信息是基于 "AMD64 Architecture Programmer's Manual. Volume 1. Application Programming".

Intel64 体系结构,在我们看来,就是一个简单但是非常有效的对于现有的商用x86体系结构的反向兼容。Intel64 加入了64位地址寻址的内容,同时扩展了资源来更好支持高性能的64位程序。陈旧的16位和32位的应用和操作系统,不需要进行额外的修改或者是重新编译,就可以在64位体系结构上运行。

64位体系结构出现的原因在于应用需要更大的寻址空间。这些应用可能是高性能的服务器,数据管理系统,CAD或者游戏。这些应用将从64位地址空间和更多地寄存器中得到大量的性能提升。在陈旧的x86系统中,只有少量的寄存器存在,因而限制了计算任务的性能。寄存器数量的增加使得能够进一步提高应用的性能。

让我们首先来看一下x64体系的优势。

l  64位寻址空间

l  扩展的寄存器组

l  开发者熟悉的命令集

l  可以在64位结构的操作系统上运行32位程序

l  可以直接使用32位操作系统

64位操作系统

基本上所有现在的操作系统都有支持64位体系结构的版本。 例如,Mircosoft就发布了Windows XP x64。大型的UNIX的开发者也发布了64位版,例如Linux Debian 3.5 x86-64,但是这不代表着这些系统的全部代码是64位的。因为64位系统提供反向兼容,有些操作系统和许多应用仍然是32位。因此,64位版的Windows 使用了一个特殊的模型 WoW64 (Windows-on-Windows 64),这个模型能够翻译32位应用的调用来使用64位操作系统的资源。

地址空间

虽然64位处理器理论上能够支持16 Ebytes (2^64)的内存空间,Win64现在仅仅支持16Tbytes (2^44)的空间。造成这个现象的原因有一些:现代的处理器仅仅能够提供1Tbyte (2^40)的物理存储的寻址。这个体系(不是这个硬件部分)可以扩展到支持4 Pbytes (2^52)的空间,但是在这种情况下你需要大量的内存来存储分页表。

除了上述描述的局限以外,每一种64位Windows版本的上内存的大小取决于Mircosoft的商业决定。不同的Windows版本有不同的限制如下表所示。

 

                       

              表1 不同Windows版本所支持的地址空间

Win64 编程模型

与Win32类似的,Win64的页面大小也是4 Kbyte。最靠前的64Kbyte 地址空间是不开放的,所以最低的正确的地址是0x10000。而不像在Win32中,系统的DLL占据了超过4 Gbyte的空间。

Intel64 的编译器有一个特性:它们可以用寄存器来更有效率的传递参数给函数,而不是使用堆栈。这就使得使用Win64体系的开发人员可以丢弃调用约定(calling convention)的概念。在Win32中,你可以使用许多约定,比如__stdcall, __cdecl, __fastcall。在Win64种,只有一个调用约定。下面的例子,是来描述4个整型参数是怎样通过寄存器的。

l  RCX: 第一个参数

l  RDX: 第二个参数

l  R8: 第三个参数

l  R9: 第四个参数

在第四个参数之后的参数通过堆栈来传递。如果是要传递浮点型的参数,需要使用XMM0-XMM3 寄存器和堆栈。

在调用约定方面的区别,使得开发人员不能够在同一个程序中同时使用64位和32位的内容。用另一句话来说,如果一个应用是通过64位来编译的,所有的动态链接库也要是64位。

通过寄存器来传递参数,是使得64位程序比32位程序快的一个创新。你可以通过64位的数据结构来取得进一步的性能提升。在下一讲中我们将讨论这方面的问题。

 

第二讲 64位Windows环境对32位应用的支持

在我们开始讨论64位程序前,让我们谈论一下64位Windows系统对32位应用的反向兼容。反向兼容是通过WoW64中的机制来实现的。

WoW64 (Windows-on-Windows 64-bit) 是Windows操作系统的一个子系统,它使得能够在64位Windows系统上执行32位应用。

WoW64子系统不支持以下程序:

  1. 为16位操作系统所编译的程序
  2. 为32位操作系统所编译的内核(kernel-mode)程序

间接费用

不同处理器体系的WoW64 有一些不同。例如,为Intel Itanium 2 开发的64位Windows版本,使用WoW64来模拟x86 指令。这个模拟比起Intel64 的WoW64体系需要更多资源,因为系统在执行32位程序的时候需要从64位模式转换到兼容模式。

Intel 64 (AMD64 / x64) 上的WoW64 不需要指令模拟。在这个系统上,WoW64子系统仅仅是通过在32位应用和64位Windows API之间添加额外的一层,来模拟32位的环境。在有些地方,这新加的一层可能比较薄,在另一些地方这一层比较厚。平均来说,对于一个程序,你需要期待因为这一个层次所带来性能上2%的损失。对于有些程序来说,这个数值可能更大。2%可能并不是一个很大的数字,但是你需要铭记在心的是32位程序在64位系统中比它们在32位系统中运行的要慢。

把程序编译为64位的代码,不仅使你避免使用WoW64,同时能使你得到了性能上提升。这个可以通过体系结构上的改变,如更多的通用寄存器来解释。平均来说,对于一个程序,通过简单的重新编译,你可以期待着在性能上有5%-15%的提升。

在64位环境上运行32位程序的好处

因为WoW64,32位程序在64位系统中比它们在32位系统中运行的要慢。但是简单的32位程序可以从在64位系统上执行获得一个好处。或许你知道,如果在32位Windows系统选择“/3gb”, 程序编译时选择"/LARGEADDRESSAWARE:YES",它可以分配到最高达3 Gbytes的内存空间。同样的32位程序在64位系统可以分配大最高达4Gbytes的内存空间(现实中大约是3.5 Gbytes的内存空间)。

重定位

WoW64子系统是通过将调用重定位至文件和寄存器, 从而将32位程序与64位程序分离开来。 这样使得32位程序不会意外的接触64程序的数据。例如,一个从"%systemroot%\System32"中调用了DLL文件的32位应用程序,如果不进行隔离,那么它可能调用了一个32位程序无法兼容的64位DLL文件。为了避免这样的情况发生,WoW64位子系统将进入"%systemroot%\System32"文件夹的调用重定位到调用"%systemroot%\SysWOW64"文件夹中的文件。这种重定位使得开发者能避免兼容性的问题,因为32位应用程序需要能与它们兼容的特殊的DLL文件。

如想了解更多关于文件系统或寄存器的重定位,可以参考MSDN相关章节"Running 32-bit Applications"。

为什么32位DLL不能在64位程序中使用? 是否有方式可以避免这种局限?

现在是不能够在64位进程中调用32位DLL并执行它的代码。这种不可行是因为64位系统的设计造成的。所以说是从根本上的不可能。没有任何技术,也没有任何文档没有记录的方式可以帮助到你。为了做到这个,你必须要装载并初始化WoW64,更不用说内核结构的不同了。这代表着64位的处理器必须在运行中被处理为32位。这个话题在"Why can't you thunk between 32-bit and 64-bit Windows?". 中有更为详尽的描述。有一件事情是我建议可以尝试的,就是建立一个使用COM技术创建一个替代程序, 你可以阅读"Accessing 32-bit DLLs from 64-bit code".

但是,从32位DLL 将资源导入到64位进程中去,是比较容易的,你所需要的就是在调用LoadLibraryEx 的时候制定以下的flag:LOAD_LIBRARY_AS_DATAFILE。

逐渐放弃对32位程序的支持

微软公司为了进一步促进程序向64位迁移,会逐渐在一些版本的Windows操作系统中取消对32位程序的支持。这是一个自然的过程。当然这个过程会比较缓慢,但这个行为已经开始了。

许多管理员可能会知道一个较新的操作系统上的服务器安装和操作模式,叫做Server Core。 这个模块正是在持久的“Windows VS Linux”大战中被广泛提起。 其中一个支持使用Linux的原因就是Linux支持不需要图像接口就可以安装服务器操作。 但是,现在Windows Server

也有了这种能力。如果你在这种模式中安装系统,你将只获得系统的命令行,而不需要用户界面。

这种能力(Server Core安装)出现在Windows Server 2008. 但是在 Windows Server 2008 R2 中,另外一种创新出现使得系统更接近64位。在Windows Server 2008 R2 (Server Core )中,你可以启动或者禁用系统对32位应用程序的支持。 更重要的是对32位应用程序的支持默认是被禁用的。所以当你尝试在Server Core mode中启动32位程序的时候,你会得到一条系统消息告诉你,这是不可以的。如果你需要额外手动启用这种支持,可以通过以下命令实现:

start /w ocsetup ServerCore-WOW64

在普通的模式(完全安装),执行32位程序的支持默认是启用的。

这种趋势是十分明显的,因而现在开始创建64位版本的应用是理智的,因为64位的程序能保证在更多的操作系统版本上使用。

额外信息

Alexey Pahunov的 Russian blog 也是获取WoW64资料的好地方。Alexey是Microsoft 的员工,他参与了WoW64子系统的开发。

 

第三讲 将代码导入64位系统的优缺点

你需要带着以下的问题来学习64位系统:“ 往64位系统重新编译项目的合理性有多少?”回答这个问题,你需要花费一些时间和精力来思考。在一方面,你可能会因为要提供64位系统的应用支持,使得你在市场上落后于你的对手。 在另一方面,你可能会花费了时间在开发64位系统应用上,而这一努力并不能给你带来竞争优势。

以下是一些建议可以用来帮助你做出选择。

应用的生命期

当你的应用有一个比较短的生命期,你暂时还没有必要开发应用的64位版本。WoW64子系统使得陈旧的32位应用在64位机上也能取得比较好的表现。如果你在两年内会停止运营你的产品,你是不需要现在建立一个64位版本的。实践证明向64位系统的迁移是一个非常缓慢平和的过程。可能你的大多数用户在未来的一段时间里还是会仅仅使用你系统的32位版本。你需要知道,本教程是在2009年编写的,这时候大部分用户都还是在使用32位系统。但是很快32位程序,就会变得越来越不自然,会变得落伍的。

如果你的项目有一比较长的开发和维护时间,你需要开始建立你产品的64位版本。当然你可以慢慢来,但是你要记住的是,越迟拥有产品的64位版本,在64位系统上维护32 位版本所带来的问题将越来越多。

程序性能要求

当一个程序重新编译以适应64位版本后,程序可以应用大量的内存资源,它的速度将提高5%-15%。5%-10%的系统提升是因为64位体系结构的特点,如更多的寄存器,所导致的。另外的1%-5%的性能提升是因为抛弃了翻译32位应用使之在64位系统环境运行的WoW64层所带来。

例如,Adobe公司称新版本64位的"Photoshop CS4"比32位版本的快了12%。

需要大量的内存的应用可以期待着有更高的性能提升。比如说,图像编辑器,CAD系统,GSI CAD,数据库和其他的模型包。能将所有的数据存储在内存中,而避免了多余的从硬盘中导入的工作,使得这些应用的速度,可能不是提升了几个百分点,而是成倍的提高。

例如,Alfa-Bank 曾经在他们的IT 基础设施中使用了基于Itanium 2的平台。原因在于他们业务的发展使得现有系统无法支持不断增长的数据量。每个用户的服务延迟变得非常严重。分析显示,系统的瓶颈不在于处理器的表现,而在于32位体系结构与内存子系统的关系上,因为32位体系结构使得只能使用4 Gbyte的服务器地址空间。而它们的数据库却大于9 Gbyte。因而导致了子系统的输入输出的临界负荷。Alfa-Bank决定购买一个由2个服务器组成的集群。这两个服务器都拥有4处理器、是基于Itanium 2的、拥有12Gbyte内存的。 这个决定使得他们的性能要求达到了可以容忍的程度。这个公司的代表称,引入基于Itanium2 的服务器使得他们解决了重要问题,同时也节约了花费。

在项目中使用第三方库

在决定是否开发你产品的64位版本前,请先确认你所依赖的第三方库是否有64位版本。你需要找出第三方软件64位版本的定价是多少。这些你都可以在库开发者的网站上找到。如果,没有依赖库的64位版本的支持,可以寻找其他支持64位的库作为替代。

你所开发的库的第三方开发者

如果你在开发库,组件,或者其他需要给第三方开发者使用的程序时,你需要尽快的开发一个你的库的64位版本。否则需要64位支持的你的客户会转向其它的替代产品。例如,一些软件和硬件安全方面的开发者,都非常迟的开发64位版本,使得他们的一些客户转向了其他工具来保护自己的产品。

发布你所开发库的64位版本有另一个好处, 你可以把它作为一个单独模块来出售。因而想要开发32 位和64位的客户会要购买2个不同的授权。例如Spatial Corporation,就是按这个方式来卖他们的Spatial ACIS库的。

16位应用

如果你的应用仍然有16位的模块, 你需要丢弃它们。64位的Windows版本完全不支持16位的应用。

关于使用16位安装程序的人员,我需要解释一个事情。这样的安装程序仍然在被使用于安装一些32位应用程序。因为对于一些比较流行的16位的安装程序,它们之中包含了一些机制,使得它们能够在运行中被更新的32位安装程序。这可能使得你觉得16位的程序,在64位的系统环境中仍能使用,但这是错误的,请牢记。

汇编器代码

不要忘记了,大量的汇编器代码片是使得创建应用的64位版本更为困难的原因之一。

工具箱

如果考虑以上提到各种因素后,你决定创建一个你的应用的64位版本,成功不是一定的。你还需要一些必要的工具,以下就是一些你可能会碰到的不愉快的事情。

首先最令人不开心的事情,就是缺少64位的编译器。当我们写本教程的时候(2009),Embarcadero还没有64位C++编译器,它有期望在2009年年底发布一个。除非你重新编写你自己的部署部分,如使用Microsoft Visual Studio时可以快速改变配置,否者你没有办法回避这个问题。但其他的问题,就没有像缺少编译器这样,容易被察觉,可能会在你将程序导入一个新的体系结构的时候发生。你可以在开始工作前,做一个调研,看所有需要的组件是否都有64位版本可以使用。不然,你将面临不愉快的事情。

做决定时,还需要注意到一个我们还没提到的问题,修改你的代码使之可以在64位模式下编译所需要的花销。我们会在之后的课程里,告诉你怎样估计这个花销。这个花销可能是非常高昂的,需要经过系统的计划和详细的时间安排。

posted @ 2013-11-11 20:39  宇月--测试开发梦想家  阅读(5120)  评论(0编辑  收藏  举报