红联Linux门户
Linux帮助

如何在Intel x86服务器上构建IBM PowerLinux应用程序

发布时间:2015-03-29 16:17:07来源:IBM作者:Freddie Mendoza, 高

IBM® Advanced Toolchain for PowerLinux 交叉编译器的实际价值在于,开发人员可在他们已熟悉的开发平台上(在大多数情况下是 x86)编译和构建 IBM Power Architecture® 应用程序。本文将介绍开发人员如何使用 Toolchain 交叉编译器,轻松地构建在 Power Architecture 上运行的源代码。本文还会回答有关交叉编译的应用程序性能、功能和在 IBM PowerLinux™ 服务器上原生地调试交叉编译应用程序的能力的问题。


简介

将在 x86 服务器上运行的 Linux® 应用程序移植到另一个平台上,比如 PowerLinux,需要设置一个不同的构建环境来编译该应用程序,是吗?没有必要。您可以在 x86 服务器上使用交叉编译器,构建针对一种不同平台架构(比如 IBM Power®)的应用程序二进制文件。交叉编译器已存在很长时间。它们主要用于为具有有限的资源的嵌入式系统构建应用程序,以便运行能够支持原生编译器的操作系统。我第一次了解交叉编译器是在参与一个针对手持设备的项目的时候。我在 x86 工作站上编写并编译源代码,并通过一个串行通信连接来将这些二进制文件加载到设备中。最近,我正在使用交叉编译器构建简单的应用程序,以便控制我所研究的一个遥控设备的伺服电动机。好了,我们进入正题。

本文将介绍 IBM Advance Toolchain for PowerLinux 中包含的交叉编译器。从这里开始,我会将 IBM Advance Toolchain for PowerLinux 称为 “toolchain”。toolchain 是一组开源开发工具和运行时库,它使用户能够在 Linux 上利用 IBM 最新的 Power 硬件特性。toolchain 本身是自成一体的,不依赖于系统 toolchain。它安装在 /opt 中,所以不会覆盖默认的 Linux 发行版 toolchain。截至撰写本文时,最新版本包含以下包的最新稳定版本:

GNU Compiler Collection(gcc、g++ 和 gfortran),以及各个针对支持的 IBM POWER® 处理器而优化的 gcc 运行时
GNU C 库 (glibc),单独针对支持的 POWER 处理器而进行了优化
GNU 二进制实用程序 (binutils)
十进制浮点库 (libdfp),进行了优化,添加了对基于 IBM POWER7® 和 IBM POWER8™ 处理器的服务器的硬件 DFP 支持
AUXV 库 (libauxv)
GNU 调试器 (gdb)
性能分析工具(oprofile、valgrind 和 itrace)
多核利用库(Intel® TBB、Userspace RCU),从 5.0-3 版本开始
以及多个支持库(比如 libhugetlbfs、zlib 等)


有关下载 toolchain 的信息,请参阅本文末尾的参考资料节。

出于本文的目的,我们将主要介绍 toolchain 交叉编译器。本文介绍如何使用 toolchain 交叉编译器,在 x86 服务器上构建适合 PowerLinux 的二进制可执行程序。文中还回答了以下问题。

在 x86 平台上构建的交叉编译应用程序,执行性能有在 PowerLinux 上原生构建的二进制程序那么好吗?
在 x86 平台上构建的交叉编译应用程序和库,是否拥有与在 PowerLinux 上构建的应用程序相同的应用程序二进制功能?
在 x86 平台上构建的交叉编译应用程序,是否会生成可在 PowerLinux 上执行原生调试的二进制程序?

为了回答这些问题,我使用了两个流行的开源应用程序 PostgreSQL 和 Apache httpd 服务器。PostgreSQL 和 Apache httpd 源代码发行版都是在 x86 服务器上使用 toolchain 交叉编译器来构建的,而且在 PowerLinux 服务器上是原生构建的。然后,这些应用程序被安装在一个 PowerLinux 服务器上的不同安装目录中并运行。我对这些应用程序运行了两个基准测试工具,比较了它们的性能和功能。

测试的结果将在以下各节中介绍。对于对重新创建测试感兴趣的读者,环境和配置 和 使用 toolchain 构建应用程序 节中分别介绍了环境配置和如何构建这些应用程序的信息。


结果

为了测试这些应用程序,我使用了一些公开的基准测试工具。对于 PostgreSQL,我使用了来自 GitHub 的 pgbench-tool。它使用了 PostgreSQL 源代码发行版随带的 pgbench 工具。对于 Apache httpd,我使用了 Apache httpd 源代码发行版随带的 apache bench (ab) 工具。请查阅本文底部的参考资料节,了解下载 pgbench-tools 的地方的信息。


PostgreSQL 测试设置和结果

在 x86 服务器上使用交叉编译器构建 PostgreSQL 应用程序后,完整的二进制程序集合被转移到一个 PowerLinux 服务器上。我们对默认的配置文件进行了以下修改:

Postgresql.conf
max_connections = 4096
shared_buffers = 2048MB
synchronous_commit = off
checkpoint_segments = 3
checkpoint_timeout = 5min

修改 PowerLinux 系统设置的 kernel.sem 值。

sysctl.conf
kernel.sem = 250     32000   32   12288

修改 pgbench-tools 的配置文件

MAX_WORKERS="32"。

根据 pgbench-tools 网站中的介绍,PostgreSQL 测试按照以下步骤运行:

创建 pgbench 和 results 数据库。
初始化 results 数据库。
创建一个包含描述的测试集。
使用 runset 脚本运行测试。
编译并提交测试结果。

有关执行这些步骤时使用的具体信息,请参阅 pgbench-tools 自述文件:https://github.com/gregs1104/pgbench-tools/blob/master/README.rst。


Postgresql 结果(交叉编译)

以下是在 Power 服务器上对交叉编译的二进制程序运行 pgbench-tools 的结果。
如何在Intel x86服务器上构建IBM PowerLinux应用程序

图 1. 交叉编译的 PostgreSQL 二进制程序的比例系数

该比例系数显示了随着数据库大小的增长,每秒处理的事务数的变化趋势。绿线表示数据库大小 (MB),红线表示每秒处理的事务数。该图表明,随着数据库大小增加,每秒处理的事务数将会下降。
如何在Intel x86服务器上构建IBM PowerLinux应用程序

图 2. 交叉编译的 PostgreSQL 二进制程序的可伸缩性图

图 2 显示了可伸缩性图。它表明随着客户端数量增加,每秒处理的事务数也会增加。


PostgreSQL 结果(原生编译)

测试原生编译的二进制程序时,使用了与交叉编译的 PostgreSQL 完全相同的配置设置和数据库位置 (/tmp/usr/local/pgsql/data)。要确保数据库是干净的,在开始测试之前请丢弃 results 和 pgbench 数据库。

Postgresql# drop database results;
DROP DATABASE

postgresql# drop database pgbench;
DROP DATABASE

比例系数和可伸缩性图如 图 3 和 图 4 所示。正如之前所提到的,该比例系数显示了随着数据库大小的增长,每秒处理的事务数的变化趋势。绿线表示数据库大小 (MB),红线表示每秒处理的事务数。
如何在Intel x86服务器上构建IBM PowerLinux应用程序

图 3. 原生构建的 PostgreSQL 二进制程序的比例系数

图 4 中的可伸缩性图显示,随着客户端数量增加,每秒处理的事务数也会增加。
如何在Intel x86服务器上构建IBM PowerLinux应用程序

原生构建的 PostgreSQL 二进制程序的可伸缩性图

您可以注意到,交叉编译的二进制程序的曲线图与原生编译的二进制程序的曲线图非常相似。这个简单测试表明,x86 服务器上的交叉编译可得到拥有与原生编译的代码相同的性能特征的二进制程序。


Apache httpd 测试设置和结果

为了测试 Apache httpd,我使用了 Apache httpd 源代码发行版随带的基准测试工具 ab。类似于 PostgreSQL,Apache httpd 是使用 toolchain 交叉编译器构建的,并将二进制程序传输到 PowerLinux 服务器。我修改了默认的 httpd.conf 文件,以便将 htdocs 目录更改为指向本地文档目录。剩余设置保留默认值。

我用于运行 ab 工具的命令行和参数如下:

#./ab -n 500000 -c 100 -g out1.data http://9.3.4.241/

我运行该命令 3 次,将输出写入到 out1.data、out2.data 和 out3.data,并使用 gnuplot 实用程序和 benchmark.tpl 文件中的参数描绘了这些文件的图像,如下所示。

# gnuplot benchmark.tpl

benchmark.tpl
# output as png image
set terminal png

# save file to "benchmark.png"
set output "benchmark.png"

# graph title
set title "Benchmark for 9.3.4.241"

# aspect ratio for image size
set size 1,1

# enable grid on y-axis
set grid y

# x-axis label
set xlabel "Request"

# y-axis label
set ylabel "Response Time (ms)"

# plot data using column 10 with smooth sbezier lines
plot "out1.data" using 10 smooth sbezier with lines title "Benchmark 1:", \
"out2.data" using 10 smooth sbezier with lines title "Benchmark 2:", \
"out3.data" using 10 smooth sbezier with lines title "Benchmark 3:"

有关 Apache 基准测试工具的更多信息,请参阅本文末尾的 参考资料 部分。


Apache httpd 结果(原生编译和交叉编译)

gnuplot 实用程序为每个测试生成一个名为 benchmark.png 的文件。这些图可以使用任何图像查看器进行查看。两幅图如 图 5 和 图 6 所示。

图 5 显示了原生编译的 httpd 的曲线图。
如何在Intel x86服务器上构建IBM PowerLinux应用程序

图 5. 原生编译的 httpd 的响应时间曲线图

图 6 显示了交叉编译的 httpd 的曲线图。
如何在Intel x86服务器上构建IBM PowerLinux应用程序

图 6. 交叉编译的 httpd 的响应时间曲线图

您可以注意到,两个曲线图显示出了非常相似的性能特征。读者可以使用不同的 Web 文档和数据执行更多测试。


功能和调试发现

除了性能之外,开发人员可能还有其他与 toolchain 交叉编译器的使用相关的问题。本节回答了与功能和调试交叉编译的二进制程序的能力相关的问题。这些问题是:

交叉编译器构建的二进制程序,在功能上是否与原生构建的可执行程序兼容?
交叉编译的二进制程序能否在 PowerLinux 服务器上进行调试?

接下来的两个简单用例有助于回答这些问题。

用例 1:将一个原生构建的 httpd 的一个或多个共享库替换为使用 toolchain 交叉编译器构建的共享库。查看原生构建的 httpd 是否仍能正常运行。
用例 2:在 PowerLinux 服务器上,将一个正在运行的进程附加一个调试器。该进程是一个从 x86 服务器构建的交叉编译的二进制可执行程序。设置一个断点,设置源代码目录,并执行一组函数。


用例 1:功能测试

以下是我在用例 1 中遵循的操作说明:

将原生构建的 httpd 安装在 /home/usr/local 中。
对 /home/use/local/bin/httpd 二进制程序运行 ldd 实用程序,以显示它的共享二进制依赖项。您可以注意到,libaprutil-1.so.0 和 libapr-1.so.0 都位于 /home/usr/local/lib 中。这些库是 httpd 需要的原生编译的库的一部分。

[root@localhost lib]# ldd ../../bin/httpd
linux-vdso64.so.1 => (0x00000fffa1140000)
libaprutil-1.so.0 => /home/usr/local/apr/lib/libaprutil-1.so.0 (0x00000fffa10c0000)
libapr-1.so.0 => /home/usr/local/apr/lib/libapr-1.so.0 (0x00000fffa1060000)
librt.so.1 => /opt/at7.0-5-rc1/lib64/power7/librt.so.1 (0x00000fffa1040000)
libcrypt.so.1 => /opt/at7.0-5-rc1/lib64/power7/libcrypt.so.1 (0x00000fffa0ff0000)
libpthread.so.0 => /opt/at7.0-5-rc1/lib64/power7/libpthread.so.0 (0x00000fffa0fb0000)
libdl.so.2 => /opt/at7.0-5-rc1/lib64/power7/libdl.so.2 (0x00000fffa0f90000)
libc.so.6 => /opt/at7.0-5-rc1/lib64/power7/libc.so.6 (0x00000fffa0da0000)
/opt/at7.0-5-rc1/lib64/ld64.so.1 => /lib64/ld64.so.1 (0x00000000267a0000)

删除共享库 libaprutil-1.so.0 和 libapr-1.so.0。
将交叉编译的库 libaprutil-1.so.0 和 libapr-1.so.0 复制到 /tmp/usr/local/lib 中。
将 /tmp/usr/local/lib 包含在 LD_LIBRARY_PATH 中。

# cd /home/usr/local/apr/lib
# rm libaprutil-1.so.0
# rm libapr-1.so.0
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/tmp/usr/local/lib

再次运行 ldd 实用程序,可以看到 httpd 现在使用了 /tmp/usr/local/lib 中的库。

[root@localhost lib]# ldd ../../bin/httpd
linux-vdso64.so.1 => (0x00000fff951a0000)
libaprutil-1.so.0 => /tmp/usr/local/apr/lib/libaprutil-1.so.0 (0x00000fff95150000)
libapr-1.so.0 => /tmp/usr/local/apr/lib/libapr-1.so.0 (0x00000fff950f0000)
librt.so.1 => /opt/at7.0-5-rc1/lib64/power7/librt.so.1 (0x00000fff950d0000)
libcrypt.so.1 => /opt/at7.0-5-rc1/lib64/power7/libcrypt.so.1 (0x00000fff95080000)
libpthread.so.0 =>/opt/at7.0-5-rc1/lib64/power7/libpthread.so.0 (0x00000fff95040000)
libdl.so.2 => /opt/at7.0-5-rc1/lib64/power7/libdl.so.2 (0x00000fff95020000)
libc.so.6 => /opt/at7.0-5-rc1/lib64/power7/libc.so.6 (0x00000fff94e30000)
libexpat.so.0 => /tmp/usr/local/apr/lib/libexpat.so.0 (0x00000fff94df0000)
/opt/at7.0-5-rc1/lib64/ld64.so.1 => /lib64/ld64.so.1 (0x0000000022730000)

启动应用程序,以查看它是否能像正常应用程序一样运行。

# cd /home/usr/local/bin
# ./apachectl start
# ps –ef | grep http
root 11022 1 0 15:41 ?00:00:00 /home/usr/local/bin/httpd -k start
daemon 11023 11022 0 15:41 ?00:00:00 /home/usr/local/bin/httpd -k start
daemon 11024 11022 0 15:41 ?00:00:00 /home/usr/local/bin/httpd -k start
daemon 11025 11022 0 15:41 ?00:00:00 /home/usr/local/bin/httpd -k start
daemon 11111 11022 0 15:41 ?00:00:00 /home/usr/local/bin/httpd -k start

在浏览器中打开运行 httpd 进程的 PowerLinux 服务器,查看浏览器上是否显示了以下消息:

它起作用了!

在此场景中,我们结合使用了一个原生编译的库和交叉编译的库。交叉编译的库是使用 ppc64 架构选项构建的。在此用例中我们可以证明,我们可以在 PowerLinux 服务器上结合使用交叉编译的库和原生编译的可执行程序。


用例 2:调试

在第二个用例中,我们尝试证明交叉编译的可执行程序可以在 PowerLinux 服务器上进行调试。以下是我在用例 2 中遵循的操作说明:

使用 gdb,附加到 httpd 进程。确保使用的 httpd 版本是 toolchain 交叉编译器在 x86 平台上构建的版本。

[root@localhost ~]# gdb attach 25412
GNU gdb (GDB) 7.6.50.20130722-cvs
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+:GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.Type "show copying"
and "show warranty" for details.
This GDB was configured as "powerpc64-linux".

(gdb)

将目录设置到源代码发行版。

(gdb) set directories /home/ProjectToolchainPLCompile/apr-1.5.1

(gdb) where
#0 0x00000fff7cb676f8 in ___newselect_nocancel () at ../sysdeps/unix/syscall-template.S:81
#1 0x00000fff7cd38274 in apr_sleep (t=<optimized out>) at time/unix/time.c:246
#2 0x0000000010034220 in ap_wait_or_timeout (status=0xfffeaa1e704, exitcode=0xfffeaa1e700,
ret=0xfffeaa1e6e0, p=0x1003d0c6138, s=<optimized out>) at mpm_common.c:195
#3 0x0000000010079238 in server_main_loop (remaining_children_to_start=<optimized out>)
at worker.c:1654
#4 worker_run (_pconf=<optimized out>, plog=<optimized out>, s=<optimized out>)
at worker.c:1823
#5 0x0000000010033430 in ap_run_mpm (pconf=0x1003d0c6138, plog=0x1003d0f3378, s=0x1003d0ef4c0)
at mpm_common.c:96
#6 0x000000001002a5d8 in main (argc=3, argv=0xfffeaa1ee28) at main.c:777

将一个函数移动到 apr_sleep。

(gdb) up
#1 0x00000fff7cd38274 in apr_sleep (t=<optimized out>) at time/unix/time.c:246
246        select(0, NULL, NULL, NULL, &tv);

列出 apr_sleep 的源代码。

(gdb) list
241       delay(t/1000);
242    #else
243       struct timeval tv;
244       tv.tv_usec = t % APR_USEC_PER_SEC;
245       tv.tv_sec = t / APR_USEC_PER_SEC;
246       select(0, NULL, NULL, NULL, &tv);
247    #endif
248    }
249
250    #ifdef OS2

与该进程分离。

(gdb) detach
Detaching from program:/tmp/usr/local/bin/httpd, process 25412
(gdb) quit


远程调试

toolchain 还包含 gdbserver 程序。它允许开发人员从一个远程 gdb 会话连接到他们的应用程序。请确保在 PowerLinux 服务器上调用 gdbserver 程序时,您使用了来自 toolchain 的 gdb。对我而言,一定要检查它是否在我的路径上。

# type gdbserver
gdbserver is hashed (/opt/at7.0-5-rc1/bin/gdbserver)

这是在 PowerLinux 服务器上使用 gdbserver 程序的一个例子。我们将附加到一个正在运行的 httpd 进程:

[root@stgisv241 bin]# gdbserver --attach 9.3.4.240:2345 22589
Attached; pid = 22589
Listening on port 2345

在 x86 服务器上,对本地服务器上的 httpd 二进制程序调用 powerpc64-linux-gdb 程序。请注意,来自 toolchain 的 gdb 版本名为 powerpc64-linux-gdb。使用的 httpd 二进制程序是 PowerLinux 服务器上运行的同一个交叉编译的二进制程序版本。

# pwd
/tmp/usr/local/bin
[root@stgisv240 bin]# powerpc64-linux-gdb ./httpd
GNU gdb (GDB) 7.6.50.20130722-cvs
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+:GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-linux --target=powerpc64-linux".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
..
Reading symbols from /tmp/usr/local/bin/httpd...done.
(gdb)

仍在 x86 gdb 会话上,在 gdb 内调用目标命令,如下面的示例所示。

(gdb) target remote 9.3.4.241:2345
Remote debugging using 9.3.4.241:2345
warning:Could not load shared library symbols for 7 libraries,
e.g. /opt/at7.0-5-rc1/lib64/power7/librt.so.1.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
Reading symbols from /tmp/usr/local/apr/lib/libaprutil-1.so.0...done.
Loaded symbols for /tmp/usr/local/apr/lib/libaprutil-1.so.0
Reading symbols from /tmp/usr/local/apr/lib/libexpat.so.0...done.
Loaded symbols for /tmp/usr/local/apr/lib/libexpat.so.0
Reading symbols from /tmp/usr/local/apr/lib/libapr-1.so.0...done.
Loaded symbols for /tmp/usr/local/apr/lib/libapr-1.so.0
….
Reading symbols from /tmp/usr/local/modules/mod_alias.so...done.
Loaded symbols for /tmp/usr/local/modules/mod_alias.so
warning:Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0x00000fffa8fe76f8 in ??()
(gdb)

可以看到一些与 gdb 无法找到库符号相关的警告消息。 gdb 命令 info sharedlibrary 显示了 gdb 未能从中读取符号的库。下面的示例输出显示了 gdb 未能从中读取符号的库。请注意,这些库是系统的一部分,除非它们在编译时打开了符号,否则您无需担忧它们。
 

(gdb) info sharedlibrary 
From               To                 Syms Read Shared Object Library 
                                      No        linux-vdso64.so.1 
0x00000fffa924ce80 0x00000fffa927e8a8 Yes       /tmp/usr/local/apr/lib/libaprutil-1.s
0x00000fffa91f7940 0x00000fffa922aa18 Yes       /tmp/usr/local/apr/lib/libexpat.so.0
0x00000fffa9192e60 0x00000fffa91ca0b8 Yes       /tmp/usr/local/apr/lib/libapr-1.so.0 
                                      No        /opt/at7.0-5-rc1/lib64/power7/librt.s
                                      No        /opt/at7.0-5-rc1/lib64/power7/libcrypt
                                      No        /opt/at7.0-5-rc1/lib64/power7/libdl.s
                                      No        /opt/at7.0-5-rc1/lib64/power7/libpthre 
                                      No        /opt/at7.0-5-rc1/lib64/power7/libc.so
                                      No        /opt/at7.0-5-rc1/lib64/ld64.so.1
                                      No        /opt/at7.0-5-rc1/lib64/power7/libnss_f
0x00000fffa8ea0c00 0x00000fffa8ea1878 Yes       /tmp/usr/local/modules/mod_authn_file
0x00000fffa8e810a0 0x00000fffa8e82108 Yes       /tmp/usr/local/modules/mod_authn_core.
0x00000fffa8e60da0 0x00000fffa8e61bb0 Yes       /tmp/usr/local/modules/mod_authz_host. 
0x00000fffa8e40f40 0x00000fffa8e41ed0 Yes       /tmp/usr/local/modules/mod_authz_group
0x00000fffa8e208e0 0x00000fffa8e20f18 Yes       /tmp/usr/local/modules/mod_authz_user.
0x00000fffa8e019e0 0x00000fffa8e046d8 Yes       /tmp/usr/local/modules/mod_authz_core.
...

如用例 2 所示,可以在调试原生编译的可执行程序的 PowerLinux 服务器上本地或远程调试交叉编译的可执行程序。另外,可以注意到二进制程序使用 –g 选项来编译,以便生成调试信息。


环境和配置

测试环境有一个 IBM Flex System® 组成,该系统有多个 IBM Flex System x240 计算节点和两个基于 IBM POWER7 处理器的节点(一个 Flex System p260 和一个 Flex System p460)。出于本项目的目的,我使用一个 Flex system x240 计算节点来交叉编译 Apache httpd 和 PostgreSQL。构建二进制程序后,我将它们转移到 Flex System p460 计算节点。图 7 显示了 IBM Flex System 测试环境的布局图。
如何在Intel x86服务器上构建IBM PowerLinux应用程序

注:以上图片上传到红联Linux系统教程频道中。

IBM Flex System 测试环境

以下是我的系统配置、操作系统级别和其他与系统设置相关的信息。


Flex System x240 计算节点

用于交叉编译二进制程序的 Intel 节点仅需要足够的处理能力和内存,以便能够构建 Power 二进制程序。配置如下:

基于内核的虚拟机 (KVM) 管理程序 Red Hat 6.5
32 个处理器
64 GB 内存
IBM Storwize® V7000 存取区域网络 (SAN) 连接磁盘

KVM Guest 系统
Red Hat Enterprise Linux 6.5
4 个处理器
16 GB 内存
一个 virtio 磁盘:100 GB
一个配置为 br0 的虚拟网络接口卡 (NIC)

所有其他 KVM Guest 系统都已关闭,以消除破坏环境的任何可能性。


Flex System p440 计算节点

Flex System p440 计算节点包含多个逻辑分区 (LPAR),其中一个配置为测试服务器。PowerLinux 服务器配置如下:

IBM PowerVM® 来宾
Red Hat Enterprise Linux 6.5
8 个处理器(专用)
32 GB 内存
Storwize V7000 SAN 连接磁盘 (50 GB)
通过虚拟 I/O 服务器 (VIOS) 共享的以太网适配器

LPAR 配置
处理模式:专用
最少处理器数:8
目标处理器数:8
最大处理器数:32
专用内存
最小内存:256 MB
目标内存:32 GB
最大内存:64 GB

虚拟以太网适配器(通过 VIOS 建立)
适配器 ID:2
VLAN ID:1
需要此适配器来激活虚拟服务器:已选择

以下是我运行的其他一些命令:

# ppc64_cpu --frequency
min:    3.56 GHz (cpu 28)
max:    3.56 GHz (cpu 4)
avg:    3.56 GHz

# ppc64_cpu --cores-present
Number of cores present = 8

# sysctl.conf
kernel.sem = 250     32000   32    12288


使用 toolchain 构建应用程序

通常,构建开源发行版的过程是一个迭代过程。如果您很幸运的话,该过程可能已构建完成。不幸的是,因为大多数开源发行版都构建于 x86 服务器之上,所以在尝试为不同架构(比如 IBM Power 架构)构建它们时可能遇到问题。

如果在 Power 上构建开源包时遇到问题,只需在互联网上搜索类似情形,查看这些已报告的问题是否与您的经历密切相关。如果是相关的,那么在大多数情况下,您可以找到如何解决该问题的建议。

对我而言,尽管为配置脚本选择正确参数后,postgresql 很好地构建完成了,但 apache httpd 没那么幸运。接下来的几节将介绍为 Power 架构构建 apache httpd 所需的修复程序。


交叉编译器经验

编写本文时,我使用的交叉编译器版本是一个仅供 IBM 内部使用的版本,它专为修复我在测试期间遇到的一个错误而构建。读者可以下载 AT 7.0-5 版,它是最新的交叉编译器(在发表本文时),拥有接下来的几段中描述的错误的修复程序。

在我尝试交叉编译 apr-1.5.1 源代码发行版时,我看到了以下编译器消息。

"sorry - this program has been built without plugin support"

按照我在互联网上搜索可能的帮助和解决方案的建议,我找到多个链接提到编译器需要使用 “plugin enabled” 选项来构建。我向 toolchain 支持小组报告了此问题,toolchain 维护人员很快就回复了我,为我提供了一个使用 plugin enabled 选项构建的修改版本。请注意,toolchain 的交叉编译器和原生编译器版本都需要使用 plugin enabled 选项构建。我能够在获得拥有该修复程序的 toolchain 版本后继续工作。

这是我使用 PowerLinux toolchain 的第一次经历。


交叉编译 httpd 2.4.3

要交叉编译 Apache httpd,需要使用另外 3 个包。它们是:apr、apr-util 和 pcre。找到下载最新包的位置后,开始使用 toolchain 交叉编译器在 x86 服务器上构建它们。

我构建 apr-1.5.1 时遇到的问题是构建 gen_test_char.o 模块。请参阅 ASF Bugzilla – 错误 51257(https://issues.apache.org/bugzilla/show_bug.cgi?id=51257) 了解有关的更多细节。我修改了 Makefile.in 文件(如下所示)并运行 buildconf 脚本,以便将更改包含在配置脚本中。

对 Makefile.in 的修改如下所示:

[root@stgisv240 apr-1.5.1]# diff -u Makefile.in ../../apr-1.5.1/Makefile.in
--- Makefile.in 2014-03-17 10:10:26.000000000 -0500
+++ ../../apr-1.5.1/Makefile.in 2014-07-03 13:36:11.125013781 -0500
@@ -46,7 +46,6 @@

CLEAN_TARGETS = apr-config.out apr.exp exports.c export_vars.c .make.dirs         build/apr_rules.out tools/gen_test_char@EXEEXT@ -       tools/gen_test_char.o tools/gen_test_char.lo \
include/private/apr_escape_test_char.h
DISTCLEAN_TARGETS = config.cache config.log config.status         include/apr.h include/arch/unix/apr_private.h @@ -132,10 +131,9 @@
make_tools_dir:
$(APR_MKDIR) tools

-OBJECTS_gen_test_char = tools/gen_test_char.lo $(LOCAL_LIBS)
-tools/gen_test_char.lo: make_tools_dir
-tools/gen_test_char@EXEEXT@:$(OBJECTS_gen_test_char)
-       $(LINK_PROG) $(OBJECTS_gen_test_char) $(ALL_LIBS)
+tools/gen_test_char@EXEEXT@: make_tools_dir
+tools/gen_test_char@EXEEXT@: tools/gen_test_char.c
+       $(BUILD_CC) $(CFLAGS_FOR_BUILD) $< -o $@
 include/private/apr_escape_test_char.h: tools/gen_test_char@EXEEXT@
$(APR_MKDIR) include/private

修改 Makefile.in 文件后,我运行 buildconf 来创建了一个新配置脚本。下一段将介绍用于配置脚本的参数和变量。顺便说一下,我是根据其他尝试在其他平台(比如 ARM)上交叉编译 Apache httpd 及其组件的开发人员的建议,为配置脚本选择配置参数的。

以下是我在 x86 服务器上运行 apr-1.5.1 组件的配置脚本时,使用的参数和环境变量。

# Config script using Power Linux toolchain on x86
BUILD_CC=gcc
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc
CPP=powerpc64-linux-cpp
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=powerpc64-linux-ld
STRIP=powerpc64-linux-strip

export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD

./configure --prefix=/tmp/usr/local/apr --host=powerpc64-linux ac_cv_file__dev_zero=no
ac_cv_func_setpgrp_void=no apr_cv_tcp_nodelay_with_cork=no ac_cv_sizeof_struct_iovec=1

BUILD_CC=gcc make install

我在 Power 服务器上了略加修改的相同发行版。请注意,用于 Power 服务器的 PowerLinux toolchain 使用了具有类似命名的可执行程序,比如从原生 cpp 和 binutils 包安装的 cpp 和 ld。修改脚本中的 CPP 和 LD 变量,如下所示。确保 Power toolchain 的路径首先传入您的 PATH 环境中。

以下是我在 Power 服务器上运行 apr-1.5.1 的配置脚本时使用的参数和环境变量。

# Config script using PowerLinux toolchain on Power
BUILD_CC=gcc
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc
CPP=cpp                                   # Note the difference
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=ld                                     # Note the difference
STRIP=powerpc64-linux-strip
#CFLAGS="-mcpu=440fp -mtune=440fp --sysroot $SYSROOT"
#LDFLAGS=-L$SYSROOT/lib

export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD

./configure --prefix=/home/usr/local/apr ac_cv_file__dev_zero=no
ac_cv_func_setpgrp_void=no apr_cv_tcp_nodelay_with_cork=no ac_cv_sizeof_struct_iovec=1
ac_cv_struct_rlimit=yes
BUILD_CC=gcc make install

以下是我在 x86 服务器上运行 apr-util-1.5.3 组件的配置脚本时使用的参数和环境变量。

# Configure script for apr-util-1.5.3 on x86
BUILD_CC=gcc
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc
CPP=powerpc64-linux-cpp
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=powerpc64-linux-ld
STRIP=powerpc64-linux-strip

export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD

./configure --prefix=/tmp/usr/local/apr --host=powerpc64-linux --with-
apr=/tmp/usr/local/apr ac_cv_file__dev_zero=no ac_cv_func_setpgrp_void=no
apr_cv_tcp_nodelay_with_cork=no ac_cv_sizeof_struct_iovec=1

以下是我在 Power 服务器上运行 apr-util-1.5.3 组件的配置脚本时使用的参数和环境变量。

# Configure script for apr-util-1.5.3 on Power
BUILD_CC=gcc
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc
CPP=cpp
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=ld
STRIP=powerpc64-linux-strip

export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD

./configure --prefix=/home/usr/local/apr --host=powerpc64-linux --with-
apr=/tmp/usr/local/apr ac_cv_file__dev_zero=no ac_cv_func_setpgrp_void=no
apr_cv_tcp_nodelay_with_cork=no ac_cv_sizeof_struct_iovec=1

以下是我在 x86 服务器上运行 httpd 组件的配置脚本时使用的参数和环境变量。

# Configure script for httpd 2.4.3 on x86
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc
CPP=powerpc64-linux-cpp
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=powerpc64-linux-ld
STRIP=powerpc64-linux-strip

export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD

./configure --prefix=/tmp/usr/local --host=ppc64 ap_cv_void_ptr_lt_long=no --with-
pcre=/tmp/usr/local/bin/pcre-config --with-apr=/tmp/usr/local/apr --with-mpm=worker--
with-apr-util=/tmp/usr/local/apr/bin/apu-1-config

以下是我在 Power 服务器上运行 httpd 组件的配置脚本时使用的参数和环境变量。

# Configure script for httpd 2.4.3 on Power
CC_FOR_BUILD=gcc
CC=powerpc64-linux-gcc
CPP=cpp
AS=powerpc64-linux-as
#ASCPP=powerpc-apm-linux-gnu-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
#CXXCPP=powerpc-apm-linux-gnu-cpp
CXX=powerpc64-linux-c++
LD=/opt/at7.0-5-rc1/bin/ld
STRIP=powerpc64-linux-strip
#CFLAGS="-mcpu=440fp -mtune=440fp --sysroot $SYSROOT"
#LDFLAGS=-L$SYSROOT/lib

export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD

./configure --prefix=/home/usr/local --host=ppc64 ap_cv_void_ptr_lt_long=no--with-
pcre=/home/usr/local/bin/pcre-config --with-apr=/home/usr/local/apr --with-mpm=worker--
with-apr-util=/home/usr/local/apr/bin/apu-1-config


交叉编译 PostgreSQL 9.4.3

不同于之前构建 httpd 所需的源代码发行版,我在交叉编译 PostgreSQL 时未遇到问题。PostgreSQL 是使用以下配置脚本来构建的。

以下是我在 x86 服务器上运行 PostgresSQL 的配置脚本时使用的参数和环境变量。

# Configure script for postgresql-9.3.4 on x86
CC=powerpc64-linux-gcc
CPP=powerpc64-linux-cpp
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
D=powerpc64-linux-ld
STRIP=powerpc64-linux-strip

export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD

./configure --prefix=/tmp/usr/local --host=powerpc64-linux --without-readline --without-zlib

与 Apache 配置脚本一样,您可以注意到针对 Power 服务器 toolchain 使用了具有类似命名的可执行程序,比如从原生 cpp 和 binutils 包安装的 cpp 和 ld。修改脚本中的 CPP 和 LD 变量,如下所示。确保 toolchain 的路径首先传入您的 PATH 环境中。

以下是我在 Power 服务器上运行 PostgresSQL 的配置脚本时使用的参数和环境变量。

# Configure script for postgresql-9.3.4 on Power
CC=powerpc64-linux-gcc
CPP=cpp
AS=powerpc64-linux-as
AR=powerpc64-linux-ar
RANLIB=powerpc64-linux-gcc-ranlib
CXX=powerpc64-linux-c++
LD=powerpc64-linux-ld
STRIP=powerpc64-linux-strip

export CC CPP AS ASCPP AR RANLIB CXXCPP CXX LD STRIP CFLAGS LDFLAGS CC_FOR_BUILD

./configure --prefix=/home/usr/local --host=powerpc64-linux --without-readline --without-zlib


结束语

toolchain 交叉编译器的实际价值在于,开发人员可在他们熟悉的开发平台上(在大多数情况下是 x86)编译和构建 Power Architecture 应用程序。从我们的用例中可以看到,toolchain 可生成像原生编译的应用程序一样高效地执行的二进制可执行程序和库。而且,交叉编译的库与原生编译的应用程序兼容。最后但同样重要的是,交叉编译的应用程序可在本地调试以及使用 gdb 调试器远程调试。

PowerLinux toolchain 与在 x86 平台上使用原生 Linux toolchain 没什么不同。希望本文能让读者很好地了解 PowerLinux toolchain 的特性和功能。


参考资料

IBM Advanced Toolchain for PowerLinux 文档:https://www.ibm.com/developerworks/community/wikis/home?lang=en#!/wiki/W51a7ffcf4dfd_4b40_9d82_446ebc23c550/page/IBM%20Advance%20Toolchain%20for%20PowerLinux%20Documentation
pgbench-tools:https://github.com/gregs1104/pgbench-tools
gdb 和 gdbserver 文档:https://sourceware.org/gdb/download/onlinedocs/gdb/index.html
PowerLinux SDK:https://www-304.ibm.com/webapp/set2/sas/f/lopdiags/sdklop.html
Apache httpd 服务器基准测试工具:https://httpd.apache.org/docs/2.2/programs/ab.html