在大多数情况下,将 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)。
方案移植
将运用程序移植到一个新渠道时,恰当的方案不可或缺。要为移植做好足够的预备,您应该:
- 以可视办法扫描代码,特别需求留意那些或许过错匹配的赋值运算,以及位操作和比较。
- 了解 IBM Power® 渠道架构关键,以及 x86 与 IBM POWER 处理器架构之间的差异 - 特别是您运用程序的字节次序。
- 确认运用哪个 Linux on Power 发行版:Red Hat Enterprise Linux 或 Novell SUSE Linux、CentOS 仍是 Ubuntu。
- 考虑运用 GNU Make 构建体系。
- 确认要运用哪个编译器:GCC 或 IBM XL C/C++ for Linux。
- 获取一个用于开发的 IBM Power 。下面列出了一些挑选:
- 查看下面的程序,确认是否有个程序能够协助加速移植并取得成功。
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. 存储十六进制值的高位优先和低位优先处理器

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’ 查看器

Migration Advisor:快速修正特性
Migration Advisor 还为一些搬迁问题供给了快速修正办法,能够将依赖于架构的代码块替换为与 POWER 处理器兼容的指令。能够经过两种办法触发快速修正:右键单击源代码中的正告并挑选快速修正选项;或许翻开 Migration Advisor Eclipse View,右键单击一个特定问题,然后挑选快速修正选项。
Migration Advisor 所供给的快速修正仅适用于:
- 特定于 x86、内置的编译器的运用
- 内联程序集的运用
- 功用降级
您能够挑选可激活或可停用的查看器。每次您修正源代码后,Migration Advisor 都将从头查看代码并更新成果,使您在对项目履行完结的从头构建之前有时机快速辨认和处理问题。图 3 显现了 Migration Advisor 窗口,其间已激活一切查看器。
图 3. 激活一切查看器

激活 Migration Advisor 查看这以后,右键单击项目并单击 Run Migration Advisor。然后,Migration Advisor 会运用启用的查看器分析代码,并在 Eclipse 视图中显现找到的潜在问题的成果(参见图 4)。
图 4. Migration Advisor 视图

图 5 显现了一个不受 Power 渠道支撑的内置插件所导致的一个实在搬迁问题的示例。为了修正该问题,能够在 Migration Advisor Eclipse 视图中双击它。然后将翻开源代码视图,杰出显现问题的精确方位。假如将鼠标移动到杰出显现的代码上方并按 Ctrl+1,则会翻开另一个弹出窗口,如图 5 所示。
图 5. 运用 Migration Advisor 进行快速修正

挑选第一个选项 Builtin quick fix。运用快速修正后的成果代码如图 6 所示。
图 6. 运用 Migration Advisor 快速修正后的代码

其他有用的 Migration Advisor 查看包括:
- 特定于 x86 的程序集查看器
- 包括位字段的结构的查看器
- Long double 运用查看器
- 功用降级查看器
- 特定于 x86 的编译器内置查看器的运用