首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

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

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

Linux Cross-platform Tool (LCT)
        SDK for PowerLinux 还提供了另一个可以在任何现有的 Intel x86 平台上运行的方便工具。它是一个命令行工具,用于识别应用程序的潜在可移植性。这样,在移植到 Linux on Power 之前,您能够快速了解源代码中的潜在问题。在安装 IBM SDK for PowerLinux 后,可以在该工具的 README 部分中找到 LCT 文档。
        IBM Rational Developer for Power Systems
        IBM Rational Developer for Power Systems 也提供了一个富桌面集成开发、移植和优化环境,用于多平台开发(IBM i、AIX 或 Linux on Power)。它的特性还包括各种移植工具,比如 Code Analysis 工具、Performance Advisor 工具和 Migration Assistant,类似于 IBM SDK for PowerLinux,这些工具可以检测 32 位到 64 位迁移问题、字节顺序问题,以及其他可能阻碍移植的操作系统问题。
        JVM
        Java 虚拟机 (JVM) 在所有平台上都以高位优先模式运行,因此常常对处理器架构带来的影响免疫。
        数据类型和对齐方式
        应用程序二进制接口 (ABI) 中重要的 有符号/无符号字符 细微差异。
        在 x86/x86_64 下,“char” 的默认值为 “signed char”,而 Power Systems 上的默认值为 “unsigned char”。在 Power Systems 上,可以使用 GCC 指令 -fsigned-char 覆盖该默认值。等效的 IBM XL 指令为 -qchars=signed。
        Linux 操作系统上的 GCC 和 XL C/C++ 编译器都提供了两种不同的编程模型:ILP32 和 LP64。ILP32 表示 Integer Long Pointer 32,是 Linux 上原生的 32 位编程环境。ILP32 数据模型提供了一个 32 位地址空间,它的理论内存被限制为 4 GB。LP64 表示 Long Pointer 64,是 Linux 上的 64 位编程环境。
        表 1 显示了 POWER 和 x86 平台上的 ILP32 和 LP64 模型中的基础数据类型中的位宽。
        表 1. POWER 和 x86 平台上的 ILP32 和 LP64 模型中的基础数据类型(位)
                                                                        基础数据类型                                                        POWER                                                        x86                                                                                                                                                                 ILP32                                                        ILP64                                                        ILP32                                                        ILP64                                                                                        char
                                默认值:x86 上为 signed - POWER 上为 unsigned                                                        8                                                        8                                                        8                                                        8                                                                                        Short                                                        16                                                        16                                                        16                                                        16                                                                                        Int                                                        32                                                        32                                                        32                                                        32                                                                                        Float                                                        32                                                        32                                                        32                                                        32                                                                                        Long                                                        32                                                        64                                                        32                                                        64                                                                                        Long long                                                        64                                                        64                                                        64                                                        64                                                                                        Double                                                        64                                                        64                                                        64                                                        64                                                                                        Long double                                                        64/128*                                                        64/128*                                                        96                                                        128                                                                                        指针                                                        32                                                        64                                                        32                                                        64                        *Linux on Power 上的 long double 的默认大小现在为 128 位。如果使用编译器选项 -qnoldb128 和 XL C/C++ 编译器,那么它们可以减少到 64 位。
        在 Power 和 x86 平台上的 /usr/include/limits.h 中,可以找到数字值的所有定义。
        许多遗留 Linux x86 应用程序在 32 位下运行。对于最新的 x86 架构(支持并鼓励采用 64 位应用程序),更多的 x86 应用程序是在 64 位模式下原生地更新或编写的。在将 x86 应用程序移植到 Power Systems 的练习中,可采用 Linux on Power 环境作为目标来匹配您的来源环境。换句话说,我们推荐首先完成初始移植,然后再考虑移植到 64 位编程模型。如果希望将 32 位 x86 应用程序移植到 64 位 Power Systems 编程模型,那么可以将迁移分为两步:
  •                 移植到 Linux on Power 32 位环境(包括测试和验证它)。
  •                 然后迁移到 64 位环境。
        如果应用程序满足以下条件:那么工程师应考虑将应用程序移植到 64 位:
  •                 能从超过 4GB 的虚拟地址空间受益
  •                 能够从更多物理内存(大于 4GB)受益,以及用户可能将它部署在具有超过 4GB 物理内存的系统上
  •                 能够从 64 位大小的长整数受益
  •                 能够使用完整的 64 位寄存器来执行高效的 64 位算法
  •                 使用大于 2GB 的文件
        一些可通过迁移到 64 位而受益的应用程序示例包括:
  •                 数据库应用程序,尤其是执行数据挖掘的应用程序
  •                 Web 缓存和 Web 搜索引擎
  •                 计算机辅助设计 (CAD)/计算机辅助工程 (CAE) 模拟和建模工具的组件
  •                 科学和技术计算应用程序,比如计算流体动力学、遗传模拟等
        应用程序可保留 32 位并仍在 64 位 Linux on Power 内核上运行,无需任何代码更改。基于 IBM Power 处理器的服务器支持 32 位和 64 位应用程序同时在 64 位架构上运行
        在不同平台(从 x86 到 Power)或编程模型(从 ILP32 到 LP64)之间移植应用程序时,需要考虑不同环境中提供的数据宽度和对齐设置之间的差异,以避免可能的性能降级和数据损坏。
        在从 x86 ILP32 移植到 POWER ILP32 或从 x86 LP64 移植到 POWER LP64 时,您可能注意到,在表 1 中,所有基本数据类型的宽度都保持相同,除了 long double 96 位变为 IPL32 上的 64/128 位,128 位变为 LP64 上的 64/128 位。这意味着您应该检查与 long double 数据类型相关的代码部分。如果计划使用 XL C/C++ 编译器,那么可以使用 -qlongdouble 编译标志在 long double 数据类型上实现最高的兼容性。
        数据对齐
        在平台之间或 32 位与 64 位模型之间移植应用程序时,需要考虑不同环境中提供的对齐设置之间的差异,以避免可能的性能降级和数据损坏。最佳实践是对数据项执行自然对齐。自然对齐表示将数据项存储在是其大小的倍数的地址上(例如,8 字节数据项存储在一个为 8 的倍数的地址中)。对于 XL C/C++ 编译器,依据 linuxppc 或位包装规则,聚合中的每种数据类型(C/C++ 结构/union 和 C++ 类)将与字节边界对齐,其中 linuxppc 是默认规则,这是一种自然对齐方式。linuxppc 也兼容默认的 GCC 对齐规则。表 2 显示了 POWER 和 x86 上的对齐规则,以及它们的数据类型宽度(以字节为单位)。
        表 2. POWER 和 x86 上的对齐值(以字节为单位)
                                                                         数据类型                                                        POWER                                                        x86                                                                                                                                                                 ILP32                                                        ILP64                                                        ILP32                                                        ILP64                                                                                                                                                 宽度                                                        对齐值                                                        宽度                                                        对齐值                                                        宽度                                                        对齐值                                                        宽度                                                        对齐值                                                                                        Char                                                        1                                                        1                                                        1                                                        1                                                        1                                                        1                                                        1                                                        1                                                                                        Short                                                        2                                                        2                                                        2                                                        2                                                        2                                                        2                                                        2                                                        2                                                                                        Int                                                        4                                                        4                                                        4                                                        4                                                        4                                                        4                                                        4                                                        4                                                                                        Float                                                        4                                                        4                                                        4                                                        4                                                        4                                                        4                                                        4                                                        4                                                                                        Long                                                        4                                                        4                                                        8                                                        8                                                        4                                                        4                                                        8                                                        8                                                                                        Long long                                                        8                                                        8                                                        8                                                        8                                                        8                                                        8                                                        8                                                        8                                                                                        Double                                                        8                                                        8                                                        8                                                        8                                                        8                                                        8                                                        8                                                        8                                                                                        Long double                                                        8/16                                                        8                                                        8/16                                                        8                                                        12                                                        4                                                        16                                                        16                                                                                        指针                                                        4                                                        4                                                        8                                                        8                                                        4                                                        4                                                        8                                                        8                        GCC 和 XL C/C++ 中的关键字 __alignof__ 允许您查询对象的对齐方式。它的语法与 sizeof 类似。例如,如果目标系统需要将一个 double 值与 8 字节边界对齐,那么 __alignof__ (double) 为 8。
        如表 2 中所示,long double 变量在 x86 上与 4 字节对齐,在 Power Systems 上与 8 字节对齐。因此,不同平台上的结构将具有不同的布局。不要硬编码任何大小和偏移,这很重要。相反,您应该使用 C 运算符 sizeof 来查询基础和复杂类型的大小。宏 offsetof 可用于从结构开头获取结构成员的偏移。
        确定要使用哪个编译器:GCC 或 IBM XL C/C++
        有两个 C/C++ 编译器可用于 Linux on Power:GCC 和 IBM XL C/C++ 编译器。GCC 针对 Linux 上的编译提供了可靠的代码移植功能,而在使用更高级的优化时,与 GCC 相比,IBM XL 编译器显著提升了性能。两种编译器都提供了 32 位和 64 位编译模式,Linux on Power 环境支持在不降低性能的情况下同时运行 32 位和 64 位代码。
        使用 GCC 编译器集进行移植
        如果项目跨多个平台而开发,而且其中 GCC 编译器是原始的编译器,那么 GCC 编译器常常用于部署针对 Linux on Power 的应用程序。性能不那么关键的应用程序(比如小型实用程序)通常属于这种情况。GCC 还允许使用一些只有 GCC 能够理解的代码原型,比如特定于 GCC 的宏。但要注意的是,许多特定于 GCC 的特性都合并在 XL C/C++ 编译器中。
        一般而言,使用 GCC 移植代码应该很简单。在大部分情况下,只需简单地重新编译和键入 make 命令即可。架构可能有所不同,而且有时可能存在库版本差异。但从很大程度上讲,它在哪个架构上运行并不重要。我们不鼓励您在 Power Linux 上编译特定于架构的标志,比如 -m486 和-mpowerpc64,因为 GCC 没有针对这些架构上的优化例程的丰富的处理器映射。同样地,如果不使用特定于架构的标志,那么不同 POWER 硬件模型上的二进制兼容性会更高。
        SLES 11 和 RHEL 6 中包含的 GCC 编译器同时支持 32 位和 64 位应用程序。在= SLES 11 和 RHEL 6 版中,默认编译模式为 64 位。
        在所有架构上,库必须使用 -fPIC 来编译;x86 默认情况下会在 GCC 中应用此标志。在 POWER 上,此标志指定将生成的代码用在一个共享对象中。请查阅 GCC 编译器手册,以便了解有关的更多信息(参见 “参考资料”)。
返回列表