当前位置: 首页 > Linux学院 > 产品应用 > IBM AIX > 将Linux C/C++应用程序从x86平台移植到IBM PowerLinux

将Linux C/C++应用程序从x86平台移植到IBM PowerLinux

2014-08-09 11:30 来源:IBM 作者:Artis Walker 人气指数: 我要评论

在大多数情况下,将 Linux 应用程序从 x86 平台移植到 Linux on Power 很简单,因为两个平台都基于来自 Novell SUSE 或 Red Hat 的同一个 Linux 版本。移植常常只需要执行一次 GNU Compiler Collection (GCC) 再编译,对一些编译器和链接器开关稍作更改。

但是,为解决突然出现的未知问题做好准备是拥有一个成功端口的重要优势。通常,如果重点关注的是移植,将优化放在以后进行,那么本文中介绍的指南、技术和工具可以最大程度地降低(甚至可能消除)移植到 Linux on Power 的难度。

在某些情况下,当您单独在一种特定硬件架构(比如 x86)上设计应用程序时,有时可能需要做一些额外的修改。本文会重点介绍与将 x86 系统上运行的 LInux 应用程序移植到基于 IBM POWER® 处理器的系统相关的一些差异,本文还提供了让 x86 代码为移植到 Linux on Power 做好准备的一些建议。

  • 您应用程序的字节顺序
  • 32 位和 64 位数据类型(长度和对齐方式)
  • 理解可用的编译器选择 - GCC(分发和 Advance Toolchain)和 IBM XL C/C++ 编译器。
  • 使用 IBM SDK for Linux 和 IBM Rational Developer for Power Systems - 使用 GNU C/C++ 编译器构建大型程序。

应用程序开发人员可以在 Power Linux 上使用一些高级工具和技术,其中包括 IBM Software Development Kit for PowerLinux (SDK),这是一个免费、基于 Eclipse 的集成开发环境 (IDE)。该 SDK 集成了 C/C++ 源代码开发与 Advance Toolchain、链接后优化和经典的 LInux 性能分析工具(包括 OProfile、Perf 和 Valgrind)。

计划移植

将应用程序移植到一个新平台时,恰当的计划不可或缺。要为移植做好充足的准备,您应该:

  1. 以可视方式扫描代码,尤其需要注意那些可能错误匹配的赋值运算,以及位操作和比较。
  2. 理解 IBM Power® 平台架构要点,以及 x86 与 IBM POWER 处理器架构之间的差异 - 特别是您应用程序的字节顺序。
  3. 确定使用哪个 Linux on Power 发行版:Red Hat Enterprise Linux 或 Novell SUSE Linux、CentOS 还是 Ubuntu。
  4. 考虑使用 GNU Make 构建系统。
  5. 确定要使用哪个编译器:GCC 或 IBM XL C/C++ for Linux。
  6. 获取一个用于开发的 IBM Power 服务器。下面列出了一些选择:
  7. 查看下面的程序,确定是否有个程序可以帮助加快移植并取得成功。

Power Development Cloud
这个完全自动化的 IBM Power Development Cloud 是一个免费的平台即服务 (PaaS),可用于使用 IBM 平台开发和演示软件解决方案。您可以利用 IBM Linux on Power 开发堆栈,它已预先配置和安装了针对从 x86 移植到 Linux on Power 的开发工具。

IBM Hardware Mall – 租赁和折扣
Hardware Mall 旨在激励独立软件供应商 (ISV) 在 IBM 平台上开发软件解决方案,为他们提供了系统硬件和适用软件的重要购买折扣和低租赁费率。

IBM Systems Application Advantage for Linux (Chiphopper)
IBM Chiphopper™ 产品是一个应用程序移植或重新托管程序,旨在免费帮助 IBM 业务合作伙伴启动、测试和支持其在竞争平台上运行的现有 Linux 应用程序向运行 LInux 和中间件平台的 IBM Power Systems™ 的移植。

IBM Innovation Center
IBM Innovation Center 提供了培训和一对一指导,涉及从构建到营销和销售解决方案的方方面面。IBM Innovation Center 团队随时准备帮助您实现开发目标

您可以在 解决方案开发硬件 网站上找到并利用所有这些服务。

理解 Power 平台的差异

您要移植到的 Power 硬件平台,确定了您在编译应用程序时想要使用的优化选项。您应考虑以哪个处理器版本为基础,例如 IBM POWER5、IBM POWER6®、IBM POWER7® 或 IBM POWER8™。为基于 POWER 处理器的系统开发一般性的代码非常容易,最终的应用程序将在多个系统上正常运行。针对 IBM 较新的几代 POWER 产品开发应用程序也很容易。一个重要的选择是选择使用 GCC 编译器还是 XL C/C++ 编译器。更多细节将在本文后面讨论。

编译器:

多年来,GCC 技术已得到显著改进,能够为基于 IBM POWER7 和 POWER8 处理器的服务器提供经过调优的应用程序。此外,如果性能是终极目标,那么 IBM XL 编译器可以实现更高的性能。

  • 如果在 Linux on x86 上使用 GCC,推荐使用 GCC 完成初始移植。Linux on Power 上的 GCC 技术已显著改进,熟悉 GCC 会使得以它为基础进行移植变得更轻松。
  • 如果需要的话,您还可以使用 IBM XL C/C++ 编译器。
  • 如果在 Linux on x86 上使用 Java™,那么推荐从 IBM 网站下载并使用合适的 IBM Java 工具包。

编译器标志:

移植到基于 POWER 处理器的服务器时,可以在 XL C/C++ 编译器中对 -qarch 和 -qtune 使用不同标志,或者在 GCC 编译器编译器中对 -mcpu 和 -mtune 使用不同标志来优化应用程序。但是,对于初始移植,为了最大限度降低难度,最好使用基于 Power 的最常见的 –qtune=ppc和 –mcpu=power。具体的标志和使用它们的时机将在本文后面讨论。

确定使用哪个 Linux on Power 发行版

来自 Novell 和 Red Hat 的最新的操作系统产品(本文发表时)提供了完成企业级部署所需的技术、支持和可靠性。首选产品的选择通常在一个公司或组织内要考虑的事项。

  • SUSE Linux Enterprise Server (SLES)。
  • Red Hat Enterprise Linux (RHEL)。

使用 SLES 还是 RHEL 的决定不会对移植过程产生直接影响。但是,SUSE 和 Red Hat 拥有不同的发布和更新周期,在二进制兼容性上具有不同的策略,从长远角度讲,这些可能影响您的应用程序更新决策。此外,Red Hat 和 SUSE 发行版按相同的时间表发布对 Intel® 和 Power 的支持。

迁移到 GNU Make

如果目前尚未使用 GNU Make 构建应用程序,那么您可以考虑迁移到该应用程序。一种不错的编程实践是:使用一个能控制可执行文件的生成的工具,而不依赖于脚本或直接调用编译器来生成可执行文件。大多数 C 和 C++ 编程人员都使用 Make 作为这样的工具。切换到 GNU Make,这样您就能通过同一个构建控件 makefile 在多个平台上执行一致的构建操作。GNU Make 同时具有 SLES11 和 RHEL6 版本。有关 GNU Make 的更多信息,请参阅 “参考资料” 部分。

假设您的 Linux on x86 应用程序是使用 GCC 构建的,那么我们推荐首先使用 GCC 在 Power 上重新编译的简单方法。后续步骤将会添加简单的调优和优化选项供考虑。如果需要的话,接下来的一个步骤将是考虑 IBM XL 编译器,以便实现针对特定 IBM Power Architecture® 级别调优的更高性能。

理解 x86 与 Power Architecture 衍生产品之间的差异

在将 x86 Linux 应用程序移植到 Power Systems 之前,您应该知道一些特定于架构的差异。在接下来的两节中,我们将详细介绍一些特别值得注意的架构差异:

  • 字节顺序
  • 32 位和 64 位应用程序环境中的数据类型长度
  • 架构中的数据对齐方式差异

我们稍后将会介绍对比 x86 和 Power 应用程序时的一些额外的考虑因素。优化考虑因素示例包括使用多个线程优化吞吐量,评估简单锁定模式的使用,等等。

字节顺序

尽管 POWER 处理器可同时支持高位优先和低位优先(字节排序模式),但最新的实现都使用一种高位优先架构,而 x86 处理器使用了一种低位优先架构。本节介绍字节顺序问题,以及处理它们的技术。在将低级 应用程序、设备驱动程序或数据文件从 x86 架构移植到 Power Architecture 期间,开发人员通常会遇到一些字节排序问题。高级 应用程序在移植时很少遇到字节顺序问题,但在从 x86 移植到 Power 时需要解决此问题。

字节排序会影响整数和浮点数据,但不会影响字符串,因为它们会保持编程人员看到和想要的字符串顺序。所以,原始 ASCII 文本文件可正常使用,但与机器独立的数据文件可能受到硬件字节顺序问题的影响。例如,JPEG 文件被存储为高位优先格式,而 GIF 和 BMP 文件被存储为低位优先格式。

高位优先和低位优先

字节顺序指数据元素和它的各个字节在内存中存储和寻址的方式。在多位数中,具有更高数量级的位被视为更重要的位。例如,在 4 位数 8472 中,4 比 7 更重要。类似地,在多字节数字数据中,字节持有的值越大,它就越重要。例如,十六进制值 0x89ABCDEF 可拆分为 4 个字节:0x89、0xAB、0xCD 和 0xEF,分别具有算术值 0x89000000、0xAB0000、0xCD00 和 0xEF。显然,字节 0x89 是最大的值;因此它是最重要的字节,而字节 0xEF 是最小的部分,因此是最不重要的字节。

将一个数字放在内存中时,从最低的地址开始,只有两个有意义的选项:

  • 首先放置最不重要的字节(低位优先)。
  • 首先放置最重要的字节(高位优先)。

下图显示了高位优先和低位优先处理器如何将 32 位十六进制值(比如 0x89ABCDEF)放入内存中:

图 1. 存储十六进制值的高位优先和低位优先处理器


将Linux C/C++应用程序从x86平台移植到IBM PowerLinux

0x89 是最重要的字节,而 0xEF 是最不重要的字节。在高位优先系统上,最重要的字节放在最低的内存地址上。在低位优先系统上,最不重要的字节放在最低的内存地址上。

如果程序将一个单词写入内存中,然后读取相同位置作为一个单词,那么字节排序不存在问题,因为在采用一致的方式引用某个变量时,看到的会是同一个值。如果程序尝试一次读取同一个值的一个字节(在写入一个单词时),根据处理器采用低位优先还是高位优先格式,它可能获得不同的结果。

IBM POWER 处理器系列是使用高位优先数据布局的系统示例,而 x86 处理器系列是使用低位优先数据布局的系统示例。识别依赖于字节顺序的代码段,并将它们转换为等效的高位优先格式,这在将 x86 应用程序迁移到 Power 平台期间很重要。

处理字节顺序

本节将介绍如何识别代码中依赖于字节顺序的区域,并将它们转换为正确的字节顺序格式的方法。

依赖于字节顺序的代码
数据引用上的非一致性是 C 语言的优势,这使得它在编程系统级软件(包括操作系统和设备驱动程序)中变得很流行。此优势包括类型转换、指针操作、union、位字段、结构和灵活的类型检查。但是,同样是这些特性,它们也可能是字节顺序可移植性问题的来源。作为示例,请考虑以下两个代码清单:

清单 1. 使用指针的非一致数据引用

#include <stdio.h>
int main(void) {
  int val;
  unsigned char *ptr;

  ptr = (char*) &val;
  val = 0x89ABCDEF; /* four bytes constant */
  printf("%X.%X.%X.%X\n", ptr[0], ptr[1], ptr[2], ptr[3]);
  exit(0);
}

清单 2. 使用 union 的非一致数据引用

#include <stdio.h>
union {
  int val;
  unsigned char c[sizeof(int)];
} u;

int main(void) {
  u.val = 0x89ABCDEF; /* four bytes constant */
  printf("%X.%X.%X.%X\n", u.c[0], u.c[1], u.c[2], u.c[3]);
  exit(0);
}

在 x86 系统上,结果为:

 EF.CD.AB.89

在基于 POWER 处理器的系统上,结果为:

 89.AB.CD.EF

字节顺序问题表现为 val,它从最重要的字节开始逐个字节地读取数据。

如何确定系统的字节顺序

在 Linux 中,GNU_C 预处理器通常会自动提供一组常用的预定义宏,它们的名称以双下划线开始和结束。一组对确定使用的系统的字节顺序最有用的宏是 __BYTE_ORDER__、__ORDER_LITTLE_ENDIAN__ 和 __ORDER_BIG_ENDIAN__。

/* Test for a big-endian machine */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* Do big endian processing */

编写字节顺序中立的代码

如果程序模块在跨具有不同字节顺序的平台移植时能够保留其功能,那么它就是字节顺序中立的。换句话说,它的功能与运行它的平台的字节顺序无关。以下是一些编写字节顺序中立的代码的建议:

  • 使用宏和指令
    要让代码变得可移植,可以使用宏和条件编译指令,如清单 3 和清单 4 所示。

清单 3. 使用指令让字节顺序效果中立化

#include <stdio.h>

#define BIG_ENDIAN 1
#define LITTLE_ENDIAN 0
#define BYTE_ORDER (( htonl(1)==1) )   //  returns 1 or 0 depending on platform


union {
  int val;
  unsigned char c[sizeof(int)];
}u;

int main(void) {
  u.val = 0x89ABCDEF;
  #if (BYTE_ORDER == BIG_ENDIAN)
  printf("%X.%X.%X.%X\n", u.c[0], u.c[1], u.c[2], u.c[3]);
  #else /*!BYTE_ORDER == BIG_ENDIAN*/
  printf("%X.%X.%X.%X\n", u.c[3], u.c[2], u.c[1], u.c[0]);
  #endif /*BYTE_ORDER == BIG_ENDIAN*/
  exit(0);
}

清单 4. 使用宏交换字节(对在运行时确定字节顺序很有用)

//  Useful Endian Neutral Macros

#include <endian.h>        

#if __BYTE_ORDER == __BIG_ENDIAN
// No translation needed for big endian system
#define sw2Bytes(val) val
#define sw4Bytes(val) val
#define sw8Bytes(val) val
#else
//  Little Endian:Translate
// Swap 2 byte, 16 bit values:

#define sw2Bytes(val) \
 ( (((val) >> 8) & 0x00FF) | (((val) << 8) & 0xFF00) )

// Swap 4 byte, 32 bit values:

#define sw4Bytes(val) \
 ( (((val) >> 24) & 0x000000FF) | (((val) >>  8) & 0x0000FF00) | \
   (((val) <<  8) & 0x00FF0000) | (((val) << 24) & 0xFF000000) )

// Swap 8 byte, 64 bit values:

#define sw8Bytes(val) \
 ( (((val) >> 56) & 0x00000000000000FF) | (((val) >> 40) & 0x000000000000FF00) | \
   (((val) >> 24) & 0x0000000000FF0000) | (((val) >>  8) & 0x00000000FF000000) | \
   (((val) <<  8) & 0x000000FF00000000) | (((val) << 24) & 0x0000FF0000000000) | \
   (((val) << 40) & 0x00FF000000000000) | (((val) << 56) & 0xFF00000000000000) )
#endif
int main(void) {
  int a=0x11121314;
  int b;
  b = sw4Bytes(a);      // b is 0x12 in LE and BE
}
  • 使用编译时选项
    实现此目的的另一种方式是在编译器命令行上将 BYTE_ORDER 的值定义为 -DBYTE_ORDER=BIG_ENDIAN。在一个具有不同字节顺序的新平台上编译时,这会消除编辑设备驱动程序或应用程序中的每个文件的需求。只需编译用于构建该驱动程序或应用程序的 makefile。

字节顺序:特定于 Linux

事实证明,Linux 内核提供了一组特定的系统宏,它们可以从低位优先到高位优先和从高位优先到低位优先执行 16、32 和 64 位交换。这些宏对从 Linux x86 移植到 Linux on Power 以及让您大代码对字节顺序中立都很方便,无需担忧会在代码中编写大量 #ifdef __LITTLE_ENDIAN 条件指令。

例如:

cpu_to_le16(u16); // converts CPU endianness 4 bytes to little-endian

le16_to_cpu(u16); // converts little-endian 4 bytes to CPU endianness

这两个宏将一个值从 CPU 使用的字节顺序转换为一种无符号、低位优先、32 位数字,或者执行反向转换。例如,在 Linux on Power 系统上,le16_to_cpu(u16) 将低位优先转换为高位优先,而 cpu_to_le16(u16) 将高位优先转换为低位优先。根据使用的宏和运行的是哪个系统,如果没有工作要做,那么它们将会返回原始值。

这些宏和其他许多宏位于: /usr/include/linux/byteorder/big_endian.h> 和 /usr/include/linux/byteorder/little_endian.h 中。

您可以查看这些头文件来找到您需要的宏。您还可以根据名称中的模式推断出它们的用途。

您可以使用预定义的 GNU_C 预处理器指令,轻松地包含正确的 include 文件,如下所示:

#include <endian.h>

#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
   #include <linux/byteorder/big_endian.h>
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
   #include <linux/byteorder/little_endian.h>
#else
   //  …user defined endian header
#endif

其他字节顺序考虑因素

从 x86 移植到 Power 时,不依赖于外部数据文件并且遵守严格的 C ANSI 编程标准的高级应用程序或许能够顺利地移植到 Linux on Power,且不会出现字节顺序问题。但是,字节顺序是一个需要理解的重要概念,而且在代码中识别这些漏洞的能力能够使得向 Linux on Power 的迁移变得很容易。

此外,在下一节中,我们将重点介绍 IBM Linux SDK 中提供的其他代码分析工具,它们可以帮助识别字节顺序问题。

选择要使用哪些迁移工具

类似于机械领域,移植工程师的 “技术” 工具箱中必须有许多工具,而且知道使用哪个工具可用来最大限度降低移植的难度。IBM Linux on Power SDK 和 IBM Rational Developer for Power Systems 都是独立、完整的集成开发环境 (IDE),可用于简化 Power 服务器上的移植和开发,是开发人员在移植到 Linux on Power 时可以使用的优秀技术工具。

IBM SDK for PowerLinux with Migration Advisor

IBM Software Development Kit for PowerLinux (SDK) 是一个免费、基于 Eclipse 的 IDE。该 SDK 集成了 C/C++ 源代码开发与 Advance Toolchain、链接后优化工具(比如 FDPR)和经典的 LInux 性能分析工具(包括 OProfile、Perf 和 Valgrind)。此外,IBM SDK for PowerLinux 中有一个叫做 Migration Advisor 的工具。Migration Advisor 工具的一个特性是代码检查器 和代码修复 特性,该工具可以分析代码中的 Linux/x86 漏洞,为您提供快速修复代码中的漏洞的选项或者提供手动修复它的建议。例如,下面的转换是从 x86 Linux 移植到 Linux on Power 时一种典型的字节顺序潜在问题。消息 “Cast with endianness issue checker” 表示存在这样的漏洞。

void foo() {
    short int val = 0xFF00;
    char *char_pointer = (char *) &val;     
    //This prints 0 in x86 (or x86_64) machines and ff in ppc (or ppc64) machines.
    printf("%x\n", *char_pointer);
}

Migration Advisor 使用 Eclipse CDT Code Analyzer (Codan) 源代码分析器来查找 C/C++ 源代码中的潜在迁移问题,比如可能在 x86 和 POWER 服务器上运行时生成不同结果的代码块。要查找源代码中的问题,Codan 会分析 C/C++ 源代码抽象语法树 (AST),查找可能与 Power Architecture 不兼容的代码段。在找到潜在问题时,Migration Advisor 会保存该问题在代码中的位置,并在源代码中的这个特定位置添加一条警告。目前,Migration Advisor 仅兼容 C/C++ 代码。

以下是在 IBM SDK for PowerLinux 中使用 Migration Advisor 的屏幕截图。

图 2. 运行 Migration Advisor ‘Union with Endianness Issues’ 检查器


将Linux C/C++应用程序从x86平台移植到IBM PowerLinux

Migration Advisor:快速修复特性

Migration Advisor 还为一些迁移问题提供了快速修复方法,能够将依赖于架构的代码块替换为与 POWER 处理器兼容的指令。可以通过两种方式触发快速修复:右键单击源代码中的警告并选择快速修复选项;或者打开 Migration Advisor Eclipse View,右键单击一个特定问题,然后选择快速修复选项。

Migration Advisor 所提供的快速修复仅适用于:

  • 特定于 x86、内置的编译器的使用
  • 内联程序集的使用
  • 性能降级

您可以选择可激活或可停用的检查器。每次您修改源代码后,Migration Advisor 都将重新检查代码并更新结果,使您在对项目执行完成的重新构建之前有机会快速识别和解决问题。图 3 显示了 Migration Advisor 窗口,其中已激活所有检查器。

图 3. 激活所有检查器

将Linux C/C++应用程序从x86平台移植到IBM PowerLinux

激活 Migration Advisor 检查其后,右键单击项目并单击 Run Migration Advisor。然后,Migration Advisor 会使用启用的检查器分析代码,并在 Eclipse 视图中显示找到的潜在问题的结果(参见图 4)。

图 4. Migration Advisor 视图

将Linux C/C++应用程序从x86平台移植到IBM PowerLinux

图 5 显示了一个不受 Power 平台支持的内置插件所导致的一个真实迁移问题的示例。为了修复该问题,可以在 Migration Advisor Eclipse 视图中双击它。然后将打开源代码视图,突出显示问题的准确位置。如果将鼠标移动到突出显示的代码上方并按 Ctrl+1,则会打开另一个弹出窗口,如图 5 所示。

图 5. 使用 Migration Advisor 进行快速修复


将Linux C/C++应用程序从x86平台移植到IBM PowerLinux

选择第一个选项 Builtin quick fix。应用快速修复后的结果代码如图 6 所示。

图 6. 应用 Migration Advisor 快速修复后的代码


将Linux C/C++应用程序从x86平台移植到IBM PowerLinux

其他有用的 Migration Advisor 检查包括:

  • 特定于 x86 的程序集检查器
  • 包含位字段的结构的检查器
  • Long double 使用检查器
  • 性能降级检查器
  • 特定于 x86 的编译器内置检查器的使用

大家感兴趣的内容
小伙伴最爱的新闻
小伙伴还关注了以下信息
小伙伴关注的焦点

小伙伴都在关注的热门词

新服 缤纷活动 航海世纪 芈月传 暗黑道具 萌乐网 苹果发布会 最新谍照 三国令 剑雨江湖 怎样修炼战骑 页游 怎样修炼伙伴 木甲世界 仙侠道2 推黑科技 页游模式 武圣试炼场 街机玩法 蓝月传奇 个人BOSS玩法 哥们网 九阴绝学 仗剑出鞘 全新模式 范伟打天下 全新元神玩法 七大神兵简介 新手攻略 跑腿任务 门派五行 城战礼包 页游界 泥石流 傅园慧 经典网页游戏 耐玩 盘点 玉石攻略 提升角色 大黑 实装属性 神兵攻略 问鼎莽荒 莽荒纪 手持神兵 土豪梦 万世 开学清单 财富赚不停 天书世界 大黑游戏 资源战场 ppwan 天问 激战 全国大战 雄霸一方 新增宠物技能 绝对小能手 花千骨 三尾章鱼 风色轨迹 双枪手 弑之神 缤纷好礼 惊喜六重连 帮会 中秋福利 自制月饼 九阴真经 玩家 五周年纪念 纪念银币 名动三界 新服资料片 画江山 勇战妖魔 邪恶势力 上古降魔 老司机玩法 坐骑揭秘 黑科技 竞技场攻略 铁血皇城 披风玩法 书剑恩仇录 装备强化攻略 野外BOSS玩法 全网曝光 赤壁传说 半回合制国 ACT 奇珍商城 热血战歌 传奇宝藏抽奖 打开方式 门徒 门徒获取玩法 三大萌宠简介