从Solaris向LinuxonPOWER迁移指南
ChinaUnix 发表于:12年08月17日 14:00 [转载] ChinaUnix
通常,将基于 Solaris 的应用程序移植到 Linux 是一项简单的任务,因为 Solaris 和 Linux 都是基于 UNIX® 的。要实现这个移植,通常只需在一些编译器和连接程序开关中通过较小的更改实现重新编译即可。只有当应用程序依靠于系统特定实现时,才需要对它们进行较大改动。虽然 Solaris 和 Linux 都设计为遵循标准,但是它们的实现中有时会出现差别。本指南将着重讲述这些差别,并在 Linux 端没有对等项时,提供可能的解决方案。
本文的内容组织如下:
迁移路线图
迁移事项,包括字节排列顺序以及 32 位和 64 位移植问题
Linux on POWER 的开发环境
Solaris 与 Linux 之间的差别
可用于 Linux on POWER 的性能调优工具和软件打包工具
我们将重点介绍将运行于 32 位或 64 位 SPARC、Intel® 或 AMD x86 架构之上的 Solaris 迁移到运行于 POWER 架构之上的 Linux。对于 Solaris,我们的讨论将基于版本 9 及其更高版本。对于 Linux,我们将重点讨论基于 IBM POWER 处理器的服务器中的可用发行版本:SUSE LINUX Enterprise Server (SLES) 版本 11 和版本 10 SP 2 和 Red Hat Enterprise Linux (RHEL) 版本 5 更新 2。
移植路线图
![]() |
|
步骤 1:准备
您需要了解源平台与目标平台之间的差别。例如,需要知道源平台上的字节排列顺序是否与目标平台上的字节排列顺序有所不同。如果源平台是 Solaris/x86,则您应该考虑字节排列顺序,因为 Linux on POWER 是大端字节的,而 Solaris/x86 是小端字节的。
还要确定目标平台上是否包含所有必需的第三方包(比如数据库和类库)。对于 32 位应用程序,要考虑是否有必要迁移到 64 位。在下面的 一般迁移事项 小节中,将提供字节排列顺序以及 32 位到 64 位问题的信息。
此外,要决定哪个编译器用于目标平台。如果应用程序是性能敏感的,那么还要考虑使用原始编译器。在 Linux on POWER 的开发环境 小节中,将提供关于 Linux on POWER 的可用编译器的详细信息。
步骤 2:配置
这一步中包括设置开发环境、设置环境变量、对 makefile 进行更改,等等。在结束这个阶段时,应该可以开始构建应用程序了。
步骤 3:构建
这一步中包括修复编译器错误、连接程序错误和其他信息。代码经常要多次重复执行步骤 2 和步骤 3 才能生成没有问题的构建。
步骤 4:运行时测试和调试
成功构建应用程序后,还要对其进行测试,检查运行时错误。
步骤 5:性能调优
现在,移植的代码已经可以在目标平台上运行。可以通过监控性能来确保移植的代码按照预期的那样执行。如果没有按照预期的那样执行,必须进行性能调优。在本文的 性能调优 小节中,将提供关于可用于 Linux on POWER 的性能调优工具的详细信息。
步骤 6:打包
您是否要将得到的代码传送给其他人?如果要传送,您想使用哪种打包方法?Linux 提供了多种方法来打包应用程序,比如自安装外壳脚本或 RPM。软件打包 小节中将提供关于 Linux 的软件打包的详细信息。
![]() ![]() |
![]()
|
一般迁移事项
这一节将提供何时将应用程序从 32 位迁移到 64 位的信息,以及跨越字节排列顺序障碍的应用程序要考虑的一些问题。从 Solaris on x86 平台上迁移的应用程序将跨越字节排列顺序障碍。熟悉 32 位到 64 位迁移和字节顺序的开发人员可以跳到下一小节 “Linux on POWER 的开发环境”。
32 位到 64 位
一旦决定移植到 Linux on POWER,如果应用程序目前是 32 位的,那么还要考虑将应用程序移植到 64 位。不过,不需要 64 位功能的 32 位应用程序应该保持 32 位。涉及迁移到 64 位的任何移植工作都应该分为两步:
首先,以 32 位形式迁移到目标平台。
然后才能迁移到 64 位。
否则,因为平台迁移导致的问题很容易与因为迁移到 64 位导致的问题混淆。也就是说,如果应用程序可以满足下列条件,则应该移植到 64 位:
受益于大于 4GB 的虚拟地址空间。
受益于更多的物理内存(大于 4GB),同时用户可能在拥有大于 4GB 的物理内存的系统中进行部署。
受益于 64 位整数大小。
受益于完整 64 位寄存器,以便进行有效的 64 位运算。
使用大于 2GB 的文件。
应用程序可以保持 32 位,同时仍旧在 64 位 Linux on POWER 内核中运行,而无需进行任何代码更改。基于 POWER 处理器的 IBM Linux 服务器支持 32 位和 64 位应用程序同时在 64 位架构中运行,而在这两种模式之间不会有任何性能下降。
将 32 位应用程序转换为 64 位应用程序时,可能会出现两个基本问题:数据类型不一致 和使用不同数据模型的应用程序之间的互操作。
64 位环境使用与 32 位环境不同的数据类型模型。对于 Linux on POWER,ILP 32 模型用于 32 位环境中,而 LP64 用于 64 位环境中。这两种模型之间的区别在于长整型 和指针 的大小。因此,当应用程序从 ILP32 转换为 LP64 时,数据类型中会发生基本变化。长整型和整型的大小不再相同。指针和整型的大小也不再相同。如果对象(如 struct 和 union)包含指针或长整型数据类型,那么它们的大小在 64 位环境中会比较大。通常,由这些差别引起的其他问题有:
数据截断
指针赋值
数据对齐
数据共享
IBM XL 编译器提供 -qwarn64 选项帮助检查 32 位和 64 位模式之间可能出现的数据转换问题。
将应用程序从 32 位迁移到 64 位环境的主题在其他文章中已经进行了大量讲述。因此本文中我们将不再详细说明如何处理这些移植问题。(请参阅 “将 Linux 应用程序移植到 64 位系统” 了解更多信息)。
字节顺序(字节排列顺序)
因为 SPARC 和 POWER 架构都是大字节端的,所以在这些平台之间移植应用程序时,不会存在字符排列顺序问题。然而,如果将 Solaris on x86 应用程序移植到 Linux on POWER,可能需要处理字节排列顺序可移植性问题,因为 x86 是小字节端架构。
在将应用程序从一种架构类型迁移至另一种架构类型的过程中,经常会遇到字节排列顺序(endianness)问题。字节排列顺序 是数据元素及其单个字节在内存中存储和表示时的顺序。有两类字节排列顺序:大端字节 和小端字节。
对于大端字节处理器,比如 POWER、PowerPC™ 和 SPARC,在将字放在内存中时,是从最低位地址开始的,首先放入最有效的字节。另一方面,对于小端字节处理器,比如 Intel 和 Alpha 处理器,首先放入的是最低效的字节。
图 1 显示了大端字节和小端字节处理器如何在其内存中放置十六进制值,比如 0x89ABCDEF:
图 1. 字节顺序(字节排列顺序)
出现字节排列顺序问题的原因之一是不一致的数据引用。它经常表现为由于数据元素转换、使用联合数据结构或使用和操作位域导致数据类型不匹配。清单 1 说明了因为使用指针进行不一致的数据引用而引起的字节排列顺序问题:
清单 1. 不一致的数据引用
int main() { int value; char *p; p = (char*) &value; value = 0x89ABCDEF; printf("%X.%X.%X.%X\n" p[0], p[1], p[2], p[3]); return 0; } |
![]() ![]() |
![]()
|
Linux on POWER 的开发环境
这一节将描述 Linux on POWER 开发环境的基础元素,包括发行版、编译器和 Java™ 技术的应用。
Linux 发行版本
有两个一流 Linux 供应商提供了 Linux for POWER 的企业版:SUSE LINUX 和 Red Hat。虽然 Linux 社区非常倚重这两个版本,但是它们不断推出新的版本时,发行版和版本的差异越来越大。大部分开发人员应该能够顺利在这两个产品之一的相同代码基础上部署系统的软件:
SLES11
于 2009 年初发行,Novell 的 SUSE Linux Enterprise Server 版本 11 提供新的内核改进、虚拟化改进、管理、硬件支持和互操作性。它在数据中心包含用于处理任务关键型工作负载的特性和更新。SUSE Linux Enterprise Server 提供一个开源、可伸缩并且高性能的数据中心解决方案。SLES11 基于 2.6.27 内核并提供 GCC 4.3.2、glibc 2.9 和 binutils 2.19。
SLES10 SP2
SUSE Linux Enterprise Server 版本 10 Service Pack 2 基于 Linux 2.6.16 内核并支持 Linux on POWER 硬件的所有企业特性。该开发环境提供 GCC 4.1.2、glibc 2.4.31 和 GNU binutils 2.16.91。
RHEL5.3
Red Hat® Enterprise Linux® 5.3 基于 Linux 2.6.18 内核并提供 GCC 4.1.2、glibc 2.5 和 binutils 2.17。相对以前的版本而言,RHEL5 包含许多改进。这些改进包括可切换的动态 I/O 调试器、IPv4/IPv6 性能改进,以及改善了可伸缩性和性能的内核 SMP 锁改进。
RHEL4.8
Red Hat Enterprise Linux 4.8 基于 Linux 2.6.9 内核并提供 GCC 3.4.6、glibc 2.3.4 和 binutils 2.15。不过,GCC4 包被更新到版本 4.1.2。(参考资料 部分提供一个文章链接,该文章在受支持的平台上对比了 RHEL3、RHEL4 和 RHEL5 的特性)。
编译器
与 Solaris 相似,除 GNU Compiler Collection 之外,Linux on POWER 还提供了高性能编译器集合 —— IBM XL C/C++ 编译器集合。XL C/C++ Advanced Edition for Linux Web 站点中有关于其许可证的详细信息。(参考资料 部分提供相关链接)。下面简单概述每组编译器及其优势:
GCC
对于跨多个平台开发的项目(其中 GCC 编译器为原始编译器),经常使用 GCC 编译器来部署 Linux on POWER 的应用程序。对于性能不是至关重要的应用程序尤其如此;例如,一些小的实用程序。GCC 还允许使用一些只有 GCC 才理解的代码原型,比如 GCC 特定宏。然而,IBM XL C/C++ 编译器中合并了其中许多 “GCC-isms”。
Advance Toolchain
对于能够利用最新 GCC 和工具链技术的项目,希望继续使用 GCC 编译器的客户可以使用 Advance Toolchain 包。Advance Toolchain 提供更新的 GCC 编译器版本,并在使用 SLES10 和 RHEL5 时针对 Power 6 调用了运行时库。在许多情况下,对于利用在 -O3 编译级别上进行编译的 Advance Toolchain 的 GCC 编译应用程序,其性能接近于在 -O3 级别上进行编译的 IBM C/C++ 编译器。IBM 编译器的优势是性能改进和调优存在比较大的空间,这在某些情况下尤为有用。
XL C/C++
针对 Power 系统的 IBM Linux XL C/C++ 编译器已经可用。针对 RHEL5、SLES10 和 SLES11 的 XL C/C++ 编译器 10.1 版本已经可用。如果您希望在更旧的 Linux 发行版(比如 SLES 9、SLES10 sp1、RHEL5 或 RHEL 4)上进行构建,IBM 编译器的以前版本(比如 XL C/C++ 版本 8 和 9)仍然可用。XL C/C++ 编译器提供 GCC 的高性能代替品,以及许多其他特性。幸运的是,XL C/C++ 编译器生成 32 位和 64 位 GNU elf 对象,它们与 GCC 编译器生成的对象完全兼容,因为 XL C/C++ 编译器使用与 GCC 相同的 GNU 库、连接程序、汇编程序和 binutil。实际上,以前专门由 GCC 编译器提供的功能已经移植到 XL C/C++,以促进源代码兼容性;例如,一些 GCC 宏和在线功能。但是除了兼容性,XL C/C++ 还提供了无可匹敌的性能。
已经为 POWER 架构开发并修改了成熟的 XL C/C++ 优化例程并且收到了预期效果。通常对于高性能计算应用程序,尤其是那些高度依赖浮点操作的应用程序,使用 XL C/C++ 进行重新编译会很有好处。
虽然 XL C/C++ for Linux on POWER 不是免费的,然而开发人员可以免费试用 60 天。详细信息请访问 XL C/C++ for Linux Web 站点(参考资料 部分提供相关链接)。
XL Fortran
如果您希望使用 Fortran 的话,针对 Power 系统的 IBM XL Fortran 已经可用。针对 RHEL5、SLES10 和 SLES11 的 XL Fortran 版本 11.1 和 XL Fortran 版本 12.1 已经可用。详细信息请访问 XL Fortran for Linux Web 站点(参考资料 部分提供相关链接)。
Binutil
在 Solaris 10 中,可以选择使用原生构建实用程序或使用随 GNU 一起提供的实用程序。通过 Linux on POWER,GNU binutil 用于使用 XL C/C++ 编译器集合和 GCC 来生成对象。GNU Binutils 站点中非常详细地讲述了 GNU binutil。(参考资料 部分提供相关链接)。
Java 技术
如果 Java Runtime Environment 与开发软件平台的 Java Developer Kit (JDK) 兼容,Java 技术允许开发人员跨多个平台进行部署,而不用重新编译代码。通过 IBM Developer Kit for Linux, Java Technology Edition 版本 1.4.2、5.0 和 6.0,RHEL4、RHEL5、SLES9、SLES10 和 SLES11 都支持 Linux on POWER Java 开发。这一套开发人员套件有 32 位版本和 64 位版本,可从 IBM 免费下载(见 参考资料)。
![]() ![]() |
![]()
|
Solaris 和 Linux on POWER 之间的差别
在这一节中,将了解 Solaris 与 Linux on POWER 之间的差别,其中包括系统调用、信号、数据类型、makefile、编译器选项、连接程序选项和线程库等。
系统调用和库函数
系统调用是用户程序使用的接口,它可以使内核代表调用线程或进程执行特定函数。要执行系统调用,还需要授权内核模式的上下文切换。库函数是普通 C 函数。它们没有任何上下文切换资源损耗,因为它们是使用其每个进程的地址空间的一部分。一些 Solaris 系统调用和库函数可能不能用于 Linux 中。发生这种情况时,可能要在 Linux 中实现打包器调用。
Linux on POWER 目前提供了 300 多种不同的系统调用。/usr/include/asm-powerpc/unistd.h 或 /usr/include/asm/unistd.h 中包含系统调用列表,具体目录取决于您使用的发行版。
下面是 Solaris 和 Linux 之间不兼容的一些例子:
regexp() 和 regcmp():如果您在 Solaris 上使用 regexp() 和 regcmp(),则在 Linux 上需要将它们替换为 regexec() 和 regcomp()。
文件系统接口例程:Solaris 文件系统例程使用 vfstab 结构,函数名中包含 vfs,比如 getvfsent。Linux 提供等同的接口,但是例程使用 fstab 结构,例程名称中包含 fs,比如 getfsent。Solaris 中的 vfstab 结构是在 /usr/include/sys/vfstab.h 中定义的。Linux 中的 fstab 则是在 /usr/include/fstab.h 中定义的。
Device Information Library Functions (libdevinfo):libdevinfo 库包含一组接口,用于访问设备配置数据,如主号码和辅助号码。标准 Linux 安装不支持这一点。
CPU Affinity:在默认情况下,多处理器系统中的进程在多个 CPU 之间切换。在某些情况下,通过明确地将进程绑定到特定 CPU(分配 CPU 亲和力)可以提高性能。Solaris 中 CPU 亲和力的系统调用与 Linux 中的不同。Linux 2.6 内核为 CPU 亲和力提供了 sched_setaffinity() 和 sched_getaffinity()。有关的详细信息,请参阅 Linux 手册。