您的位置:首页 > 运维架构 > Linux

Linux on POWER 中的 GNU C/C++ 工具链

2006-09-21 11:50 295 查看
级别: 初级Matthew Davis, Linux Power 技术顾问, IBMGary Hook, 高级技术顾问, IBM2005 年 6 月 13 日在本文中,您将学习有关 Linux™ on POWER™ 中 GNU 工具链的知识。本文将重点介绍可用于使用 Linux on POWER 上的 GNU 编译器(compiler)、链接器(linker)和加载器(loader)的一些常用选项,还将讨论 GNU binutils,重点考虑特定于 Linux on POWER 的一些考虑事项,以及 SUSE Linux Enterprise Server Version 9 和 Red Hat Enterprise Linux Version 4 中提供的一些新特性。简介GNU 软件的一个显著优点是它来自严格的开发者社区,具有很好的可移植性。GNU 开发工具链(toolchain)是指 GNU Compiler Collection、GNU libc 以及用来编译、测试和分析软件的 GNU binutils。这些工具遵守 PowerOpen ABI 和 64 位的 PowerPC® ELF ABI Supplement 规范,从而确保与其他类似工具的二进制兼容性。此外,它们是 Linux on POWER 的默认开发工具链。尽管 GNU 工具重点强调的是兼容性,但是与其他通用开发平台相比,它们在 POWER 架构上仍然有一些特有的区别。POWER 上的指令集与其他架构有所不同,GNU toolchain 负责处理这些区别。开发人员应该理解使用 GNU toolchain for Linux on POWER 的细节。例如,在 Linux on POWER ABI 和其他通用的 ABI 之间有所差异,开发人员必须知道在开发和移植软件时,这些差异会对自己的代码产生什么影响。值得一提的是 IBM XL C/C++ 和 Fortran 编译器也会使用 GNU toolchain 来生成二进制文件。在这些相关的地方,我们将针对 XL C/C++ 对 GNU toolchain 进行讨。通过逐步解决基本操作、特定于 POWER 的操作、潜在的缺陷和 GNU toolchain 一些新开发的特性,本文解决了 GNU toolchain for Linux on POWER 的软件开发和可移植性需求问题。本文还对 GCC C/C++ 编译器、GNU 链接器和汇编程序以及其他一些 GNU binutils 进行了探索。虽然还有很多平台都没有介绍,但 GNU 手册通常都会引用一些完整介绍这些主题的资料。本文并没有讨论 Linux on POWER 系统中其他 GCC 编译器、IBM XL C/C++、Fortran 或 Java 开发的一些细节问题。我们从 GCC 编译器和编译驱动器入手开始介绍,依次介绍 GNU 链接器、GNU 汇编程序和其他的 binutils。本文没有明确地对 GNU C Library 进行讨论,因为特定于 POWER 的变体很少,应该不会影响到用户,C Library 通常也被认为是 GNU Toolchain 的一部分。在合适的地方,我们给出了在 Linux on POWER 上发现的一些细微区别,为那些熟悉其他平台上的 Linux 或者在 POWER 架构上运行的 AIX 的开发人员提供帮助。(例如,x86 和 POWER 之间就有一些区别:前者的汇编程序不同,后者在 ELF 和 XCOFF ABI 之间也有所不同。)
回页首
GNU Compiler Collection从历史传统上来说,GCC 是代表 GNU C Compiler,但是现在它代表 GNU Compiler Collection。GCC 是用于 C、C++、Objective-C、Java™、Fortran 和 Ada 编程语言的一个编译器集。不过本文的讨论仅仅局限于 C 和 C++ 编译器,尤其是那些 GCC 的操作和选项、特定于 POWER 架构的 GCC 特性操作和受 GCC 支持的最新特性,这些特性是随 Linux for POWER 架构的两个领先发行版本(Red Hat Enterprise Server AS 和 SUSE LINUX Enterprise Server)一起打包的。GCC 的基本操作GCC 的基本操作驱动着预处理、编译、汇编和链接的过程。传递给 GCC 的大部分选项实际上都会被重定向给工具链中的其他组件。有些选项,例如平台的选择、调试和优化标记,会为编译器和其他组件同时提供参数。输入选项编译器必须知道要处理的是哪种类型的输入数据。例如,C 源程序文件的处理就与 C++ 文件不同。对于编译器来说,有一个基本的隐式选项:源程序文件的扩展名。该选项将决定调用哪一个 GCC 编译器。例如,file.c 调用的是 C 编译器,而 foo.C 或 foo.cxx 则会调用 C++ 编译器。在 GCC 手册中列出了可接收源代码文件的扩展名的完整列表。下图展示了 GNU Toolchain 生成可执行程序或共享对象所应采取的步骤。GCC 驱动器通过接受一些选项对整个 toolchain 间接进行控制。图 1. 生成可执行程序或共享对象的步骤输出选项编译器还必须知道用户期望获得哪种类型的输出。GCC 驱动器可以为整个工具链的其他部分产生一些指令,从而生成最终的可执行程序,或者在生成一些中间文件时就停止。您可以使用源程序的文件扩展名或命令行选项来控制编译器的输出。表 1 对输出文件的选项进行了总结。表 1. 输出文件的选项
标记 操作 输出格式
-c 汇编,但不链接.o 文件
-S 编译,但不汇编.s 文件
-E 预处理,但不编译对 .c 文件进行预处理后的结果
例如,下面的命令可以对源文件 hello.c 进行预处理和编译,生成 hello.s 文件:
所生成的文件 hello.s 就已经可以进行汇编生成对象文件了。另外一组输出现象影响的是编译器的输出信息,而不是输出文件的格式。
-v
选项会显示编译过程的详细信息,
-###
选项的作用是显示这些详细信息,但是并不执行这些命令。后面这个选项在创建编译脚本时尤其有用。Dialect 和标准选项正如前面介绍的一样,GCC 可以为很多种语言编译二进制文件。这些语言都有一些特定变体,即方言,这些变体被概括为特殊的语言约定。GCC 可以接受一些选项来指定编译器所使用的方言。这包括标准选项,以及对标准限定进行修改的更具体的标记。GCC 支持 1990 年发布的 ANSI C Standard,并支持 1995 年所添加的扩展,以及部分支持 C99 修正标准。
-ansi
-std
标记可以用来对编译器强制施加一些限制。
-ansi
标记会禁用 GNU 的扩展(请参看下面的 表 2),例如
inline
asm
。注意其他的 GNU 关键字,例如
__inline__
__asm__
依然可以继续使用,不过这会破坏对语言标准规范的遵守。
-ansi
选项还会禁止在 C 语言中使用 C++ 风格的注释。
-std=
选项可以指定标准等级或 GNU 对该标准的扩展等级。这些选项在下表中进行了总结。可以在 GCC 手册的 3.4 节中看到所有可用规范的完整列表。(请参阅 参考资料。)表 2. 标准和标准扩展选项
-std= 标记 标准或标准扩展
c89 或 iso9899:1990 ISO C90(与 -ansi 相同)
iso9899:199409 ISO C90,1994 amendment
c99, c9x, iso9899:1999, or iso9899:199xISO C99 (并不完全支持)
gnu89ISO C90 with GNU extensions(默认)
gnu99 或 gnu9x ISO C99 with GNU extensions
c++98 Amended 1998 ISO C++ standard
gnu++98Amended 1998 ISO C++ standard, with GNU extensions (默认)
更新标准的特性如果与以前的 C 标准并不冲突,那就可以使用。即使不指定
-std=
标记,情况也是如此。例如,即使不指定
-std=c99
,也可以使用
__restrict__
,条件是它不会与所指定的旧标准冲突。有一些更加具体的标记,例如
-fno-asm
,可以用来强制是否遵从某种标准。这种类型的标记提供了一些强制关键字、通用有符号数据类型,并可以显示数据元素是保存在二进制文件的什么地方,以及其他一些信息。关于 C 和 C++ 的 dialect 选项的完整信息,请分别参阅 GCC 手册的 3.4 节和 3.5 节(请参阅 参考资料)。除了 ANSI 标准之外,GCC 还支持 GNU 对 C 和 C++ 语言的一些扩展,这些扩展在 ANSI 标准中并不支持。在本文中并没有对这些扩展过多进行讨论,但是如果开发人员希望自己的代码可以在其他 GNU 平台之间可以很好地移植,我们强烈建议开发人员要了解这些区别。在下面的 清单 1 中给出了一个主要的扩展,这是因为这种用法非常常见,而且这是一个很好的可移植扩展的例子。GNU 扩展可以使用前后的双下划线进行标记。例如,
__asm__
就是 GNU 对
asm
的扩展,它可以在规范中允许指令的操作数使用 C 表达式。现在请考虑下面这个例子,它来自于 Linux 内核的源代码,使用了 GNU 的扩展:清单 1. GNU 扩展
注意,在这个例子中使用了 inline、
asm
和 volatile 关键字的另外一种可替代形式:前后都使用了双下划线。
__GNUC__
宏定义通常是为 GCC 进行预定义的,可以用来检查在编译代码时是否使用了对 GNU 扩展的支持。您可以认为这就像是在询问某一个编译器是否是 GCC 一样。我们建议您使用 GNU 的扩展关键字来检查是否存在 GNU 扩展,从而保证与其他编译器的可移植能力。例如:
这会检查是否存在 GNU 的扩展,如果不存在,就将后面的代码中会出现的一些关键字定义为其他编译器可以识别的关键字。当使用 pedantic 警告信息调用 GNU 编译器时,所有的 GNU 扩展都会被报告为警告信息。通过在所有使用 GNU 扩展关键字的表达式之前都加上
__extension__
关键字,可以解决这个问题。记住,这是 GNU 扩展及其用法的一个例子。其他编译器也有很多特性,其中有一些都是类似的非标准特性。严谨的开发计划包括对这些扩展在可移植性和性能影响方面的理解。在 GCC 手册中完整介绍了所有的可用扩展。(请参阅 参考资料。)警告选项GCC 在报告错误消息时可以使用不同的粒度。在 GCC 手册中的 3.8 节列出了警告和错误选项。请参阅 参考资料。)除了能够打开或关闭每种类型的警告信息之外, 还有几个元选项来控制警告和错误消息的类型。这样可以让编译器进行一些严格的检查。
-fsyntax-only
选项会通知编译器只关心那些真正不符合语法规发的地方。这是编译器最松散的一种状态,与
-pedantic
选项正好相反。
-pedantic
选项会产生选定的 ISO 标准所希望的所有警告信息。这个标记还会禁用扩展,
__keywords__
和以
__extension__
标识符开始的表达式除外。
-pedantic-errors
选项会导致编译器编译器在碰到每个警告信息时就停止,仿佛遇到的是一个错误。
-Wall
现象会使用很多警告信息,但是只有警告信息,没有其他信息。
-Wall
究竟会产生哪些消息是一个经验问题。正如在 GCC 手册中介绍的一样,这个选项 " 会启用所有有关那些某些用户认为存在问题而且很容易避免的结构的警告信息 " 请参阅 参考资料)。
-Wextra
选项则会通知编译器要报告所有其他认为可能较少出现问题的警告消息。在 GCC 手册的 3.8 节中,可以看到这些标记可以捕捉到的所有警告信息的完整清单。(请参阅 参考资料。)如果一个标准可以同时使用
-std=
选项和
-pedantic
选项来测试代码是否遵守某个标准,那会很有吸引力。然而,这在实践中却并不怎样。虽然 -pedantic 选项实际上会对标准所希望产生警告的每个结构都产生警告信息,但是它并没有解决标准中的所有情况,因此它会替换成实际的标准遵守测试。调试选项交互式调试程序可以极大地加速代码中问题的分析。GNU Project Debugger,或称为 gdb,可以在程序中任何给定的地点停止,跟踪程序的执行过程,检查程序执行过程中到底发生了什么;如果程序没有正常结束,还可以修改程序的执行过程。为了在 Linux on POWER 上使用 gdb,必须使用调试选项来编译代码。在使用
-g
-ggdb
选项编译代码时,会产生 DWARF 和 DWARF2 格式的信息。
-pedantic
标记会产生 DWARF 信息供 gdb 使用。但是与大部分调试器不同,gdb 可以同时使用
-g
-O
标记(基本优化标记)。这是 gdb 特有的一个特性,在其他很多调试器中都没有这个特性,因为经过优化之后,代码的组织和执行都会发生变化。然而您也要有所准备,因为同时使用
-O
-g
会可能对代码重新进行调整,这在使用调试器时会受到影响。如果给 GCC 传递
-ggdb
选项,GDB 就可以使用意义更加丰富的 DWARF 2 格式。这同时会启用 gdb 的扩展。
-g
-ggbd
选项都可以接受一个级别参数(例如,
-ggdb1
标识级别 1)。从直观上来看,这个级别越高(一共有 3 个),调试器中可以使用的调试信息就越多。这是一个折中:调试信息越多,程序就越大,执行速度也就越慢。gcc 还有很多标记可以用来进行配置。这包括
gprof
gcov
用来搜集数据的一些选项,以及用来报告内存使用情况、优化信息的标记,等等。很多这种选项通常都是用来调试程序的,而不是用来编译代码的。最后一组调试标记是有关编译环境的。诸如
-print-file-name=
之类的选项用来验证所提供的编译环境是不是我们所希望的环境。完整的调试标记,请参阅 GCC 手册的 3.9 节。(请参阅 参考资料。)优化选项GCC 为 C/C++ 代码和所支持的其他语言提供了一个后台优化器。由于 Linux on POWER 是一个性能很高的平台,因此对于开发人员来说,理解这个优化器的操作非常重要。注意,并不是所有的优化程序都被详细记录,而是只有那些可以使用命令行选项调用的程序会有被记录。此处,介绍的这些选现并不是从它们性能的角度进行讨论的,而是从它们的移植和调试角度进行讨论的。完整的优化选项,请参考 GCC 手册的 3.10 节。(请参阅 参考资料。)分组优化标记可以让编译器使用一个标记来选择一组优化选项。它们用来对代码的性能或大小进行不同级别的优化。
-O
-O1
标记是第一个组优化标记,它包括包括了一些不用多少编译时间就可以实现的优化步骤。
-O2
实现的是那些可以用来提高性能但却不会增加程序大小的优化;比较
-O3
-O2
,针对性能进一步进行优化,而不管是否会影响程序的大小。
-Os
是对程序的大小进行优化,即使会影响程序的性能也在所不惜。注意,并没有一个分组选项可以选择使用编译器中所有可用的性能优化选项。还有一个值得注意的事项是,对于 GCC 来说,
-O
-O1
是完全相同的。但对于其他一些编译器来说,情况并非如此,这些编辑器包括 IBM XL C/C++ 编译器,该编辑器也可以在 Linux on POWER 上使用。注意,有些选项对于编译器来说是明智的,因为它们会影响到开发的各个方面,例如调试。
-fomit-frame-pointer
就是一个这种选项,在所有的 -O 级别中都会启用这个选项,它会在不需要的地方删除 frame 指针。这个选项可以提高性能,但是这个标记的规范却并不担保实现了优化。在
-fomit-frame-pointer
的例子中,这是因为 POWER 平台上的堆栈指针就是一个 frame 指针,在使用
alloca()
机制在堆栈中动态分配内存时更是如此。在这些情况中,frame 指针必须保留,以便提供反向的跟踪。这是一个启发式优化有害的例子,因此编译器会将其忽略。POWER 架构中有一个分支计数寄存器,GCC 有一个利用这种特性的选项:
-fbranch-count-reg
。该特性利用了 POWER 架构可以对计数寄存器进行消耗和分支的能力,而不是采用消耗(和 0 作比较)和有条件的分支。在从 SPARC 往 Linux on POWER 上移植程序时,要确认启用了这个选项,因为 SPARC 并不支持这种特性。如果启用了
-O2
,那么
-fbranch-count-reg
标记默认情况下是启用的。再次重申,在某些上下文中,编译器是不会应用这种优化的。在这种情况中,不包含函数调用的循环可以从这个选项中获益良多,但是在函数调用之前复制计数寄存器的内容所带来的负载可能会超过使用计数寄存器操作所带来的优点。预处理选项GNU 的预处理器是与编译器一起对源文件进行处理,它们将源程序中的文本转换成一些指令用来进行编译。GNU 预处理器是在 GCC 驱动器的控制之下自动进行操作的,GCC 驱动器中有几个选项可以用来引导预处理器的行为。与 GCC 所驱动的其他工具链工具一样,预处理器可以使用
-Wp
选项向预处理器传递预定义的选项,或者使用
-Xpreprocessor
选项向预处理器显式地传递外部指定的选项。Linux on POWER 没有 GCC 驱动器标记不能使用的预处理器选项。也就是说,我们没有什么理由去使用
-Xpreprocessor
标记,而不使用
-Wp
标记。
-undef
选项可以取消 GCC 或目标平台所特有的宏定义。在计划进行移植时,这非常有用,因为它可以帮助确定移植的问题。
-M
选项通常也非常有用,因为它可以用来显示源文件所需要的所有依赖关系。这种依赖关系乐意用来检查源代码和目标平台的可用性。
-I
选项用来包含要搜索的头文件所在的目录。如果一个依赖关系是使用
-I
选项直接指定的,并且这个包含的路径没有成功,那么需要确保系统中已经安装了所有的更新包,并应用了所有的服务包。在较低版本的 Linux on POWER 上,安装程序有些问题,没有完全安装部分系统库和头文件。具体地说,Red Hat Enterprise Linux Version 3 上 64 位的标准和兼容库就存在这个问题。RHEL3 的所有问题在 RHEL3 Update 3 中已经得以修正。汇编程序选项与预处理器类似,GNU 汇编程序也可以接受 GCC 能够识别和不能识别的一些选项:它们分别是
-Wa
-Xassembler
标记。这两个选项在后文的“GNU 汇编程序”一节中会深入进行介绍。链接器选项链接器也可以使用类似于
-Wa
-Xassembler
的选项:
-Wl
-Xlinker
。然而,与汇编程序选项不同,GCC 驱动器可以接受一些直接对链接器行为产生影响的选项。Linux on POWER 上有两种编译器:GCC 和 XL C/C++ for Linux on POWER。由于这两种编译器都使用了 GNU 工具链,因此它们生成的对象是完全兼容的。对象名的清单可以作为参数传递给 GCC 驱动器,这会告诉链接器在链接成可执行文件时包含这个对象文件。在将多个编译器产生的对象链接为可执行程序时,这个选项非常有用。例如,可以考虑这样一个应用程序:它有很多进程组件,其中一些进程需要考虑可移植性的问题。那些对性能至关重要的代码可以使用 XL C/C++ 进行编译,以便获得更好的性能;其余的代码可以使用 GCC 进行编译。这种方法最大限度地利用了编译器的性能、GNU 工具链的灵活性以及可以将这两个编译器编译出来的对象链接成可执行程序的优点。GCC 驱动器也可以接受一些参数,指定在链接时包含哪些库。
-l
选项可以接受库的名称,可以直接使用,也可以作为遵守 POSIX 规范的一个单独参数。这个参数的排序规则非常重要。库是按照指定的顺序进行搜索的。因此要确保其他库或对象所依赖的库要首先列出。虽然从理论上来说,将 32 位对象和 64 位对象链接在一起是可行的,但是目前 GNU 工具链还没有实现这种功能。从架构上来说,存在一些原因可以解释为什么没有实现这种功能。在 POWER 平台上,将整个应用程序都编译成 64 位的并不会降低程序的性能。代码生成选项有些与机器平台无关的选项可以影响生成代码的方式,在 Linux on POWER 可能会有一些特殊的影响。在将程序从 Linux on Intel 移植到 Linux on POWER 时,一个常见的变化就是对位置无关的代码的考虑。
-fpic
选项用来生成与位置无关的代码,用来在 GCC 中使用共享库使用。在很多平台上,这个选项是必须指定的,但是在 POWER 架构上,这要取决于到底是使用 32 位模式还是采用 64 位模式来编译应用程序。在 64 位模式中,所有的对象都是与位置无关的;而在 32 位模式中,您必须指定
-fpic
选项。Makefile 和编译脚本在为 Linux on POWER 配置编译标记时,就应该考虑这个问题。堆栈的反向跟踪(stack backtrace)可以用来研究程序究竟是如何执行的。如果程序出错,那么反向跟踪可以提供一些内幕信息,说明究竟是哪个函数调用应该对这个问题负责。即使程序执行成功了,反向调用也可以用来研究程序是否是按照程序员所想象得那样执行。反向跟踪依赖于构成程序的对象中的 frame 指针。为对象生成 frame 指针,既不需要 32 位的 ABI for Linux on POWER,也不需要 64 位的 ABI for Linux on POWER。这会使得调试变得更为复杂,尤其是建立反向跟踪之后。frame 的信息在 GCC 中可以使用
-fexceptions
标记来产生。这个选项会告诉 GCC 来实现在使用调试程序展开堆栈时所需要的反向跟踪信息。虽然这会增加数据的大小,但是应该不会影响程序的执行。
-fexceptions
标记对于 C++ 程序默认是启用的,而对于 C 程序默认是禁用的(这可能会需要与 C++ 对象中的异常处理程序进行交互)。因此,如果如果 C 代码希望处理 C++ 程序所触发的异常,那么就必须在 C 程序的编译标记中加上
-fexceptions
标记。在某些架构上,异常处理必须使用 Call Frame Information 指令进行管理。这些指令用来在汇编中引导异常的处理。在 Linux on POWER 上也可以使用这些指令,由于某些原因(例如,代码的可移植性),GCC 所成城的异常处理信息还是不够的。特定于 POWER 架构的选项尽管 GNU 工具链的重点是可移植性,但是每种架构都有自己特殊的优点,开发人员必须理解如何充分地利用这些优点来实现最佳的性能。这一节将介绍 GCC Linux on POWER 可以接受的特定于架构的一些选项。
Power 架构家族和 GCCPOWER 和 PowerPC 处理器从 IBM 801 到 POWER5 已经经历了一段漫长的路程,并广泛应用于各个领域:从手表到企业级的服务器无所不在。POWER 是最初的架构的名字,PowerPC 则起源于 Apple、IBM、Motorola 在 1990 年的合作项目。这两个系列是单独进行开发的,但是从发布以来,POWER5 和 PowerPC970FX 的结果就领先了业界 10 年之上。不管在多么广泛的产品中采用,这两个架构系列所具有的通用指令都可以为代码提供很好的可移植性。虽然 IBM 还会不断推出更新的与 POWER 架构类似的芯片,但是对于 GCC 来说,PowerPC 也包含了所有最新的处理器。
架构标记GCC 对于 POWER 架构可以使用两类扩展指令。第一个集合是为早期的 RS/6000 架构设计的,可以使用
-mpower
标记启用。最近的 POWER 或 PowerPC 硬件不能使用这个标记。相反,它们使用
-mpowerpc
选项,或者它们的 64 位对应的选项
-mpowerpc64
,来使用现代 POWER 和 PowerPC 硬件所通用的指令。对于那些希望仍然对传统的 POWER 硬件提供支持的开发人员来说,要么同时使用
-mpower
-mpowerpc
标记,要么一个标记也不使用,这是因为这两个标记每个都只启用了针对每一个处理器系列的扩展。如果这两个标记一个都不使用,那么就只会使用那些这两种架构所通用的那些指令。然而,要想对性能进行优化,我们建议您使用 CPU 特有的标记。CPU 特有的架构标记CPU 特有的优化标记比处理器系列标记更能提高程序的性能。这些标记会通知编译器为某个特定的 CPU 生成最优化的代码,不过这些代码可能并不能在其他平台上运行。
-mtune=
标记用来为一种给定的 CPU 指定调度参数,但是它并不会设置架构的类型、寄存器的用法以及记忆变量。这些是通过
-mcpu=
标记进行控制的。
-mtune=
标记的用法如下:
这个例子引导编译器将源文件 foo.c 和 foo2.c 编译成一个可执行文件,使用优化级别 3,并使用为 POWER5 CPU 定制的调度参数。
-mcpu=
标记的用法如下:
这个例子引导编译器将源文件 foo.c 和 foo2.c 编译成一个可执行文件,使用优化级别 3,并使用为 POWER5 CPU 定制的调度参数、记忆变量、架构类型以及寄存器的用法。熟悉 IBM XL C/C++ 的开发人员可能会注意到此处的一个差别。使用 XL C/C++ 时,对应的标记是
-qtune=
-qarch=
,分别对应
-mtune=
-mcpu=
-mtune=
-mcpu=
都可以使用 common 选项,这样会选择 Power 和 PowerPC 架构处理器通用的一个指令集。例如:
这个例子会从源文件 foo.c 和 foo2.c 生成一个使用级别 3 进行优化的二进制文件,它可以在任何 POWER 和 PowerPC 处理器上运行,只使用了这两个架构所通用的一些指令。然而,这个二进制文件的性能可能不如使用 CPU 特有的标记进行优化所得到的二进制文件的性能好。另外,
powerpc
powerpc64
power
选项都可以用来指定自己的 CPU 属性。这两个选项的全部合法范围包括对旧集合和新机器的支持。然而,POWER 架构上的企业级 Linux 发行版只支持常见的
power3
power4
power5
970
powerpc
powerpc64
选项,因为它们都有为企业级硬件所设计的相关指令集。请参阅 GCC 手册中对所支持的指令集和处理器的详细清单。(请参阅 参考资料。)Vector Multimedia eXtensionVector Multimedia eXtension,简称 VMX,是 POWER 处理器的单指令多数据(SIMD)架构的扩展。VMX 是由 Apple、IBM、Motorola PowerPC 联合开发的,每个成员都使用一个不同的名字在市场上进行销售。IBM 称之为 VMX,这是这种技术最原始的代号;而 Apple 称之为 Velocity Engine®;Motorola 使用的名字是 AltiVec®。GCC 并不能识别这种技术的商标名,但是它实现了对这些处理器指令的支持,它使用 AltiVec 作为相关标记的名字。VMX 提供了 32 个附加 128 位的寄存器来保存向量数据,这可以提供 16 个 8 位的值、8 个 16 位的值或者 4 个 32 位的值。(注意 VMX 寄存器不能操作 64 位的值。)这些寄存器和对其进行操作的 162 条处理器指令就是为什么在处理特殊类型数据时 VMX 可以极大提高性能的原因。例如,我们可以使用向量来并行处理 4 个整数,这需要为此目的而特殊编写代码。虽然 VMX 为某些算法提供了巨大的优点,但是代码的编写必须实现向量化。不幸的是,对于编译器来说,没有什么魔力可以在后台实现 "自动向量化(autovectorization)"。C 语言中有一些指令可以对底层寄存器的选择提供控制。这些指令、原型以及宏都是在 GNU 的 altivec.h 文件中定义的,可以用来帮助实现这个任务。注意在使用 IBM XL C/C++ 时,并不用显式地在源程序中包含 altivec.h,而在使用 GCC 时,则必须显式地包含这个文件。GCC 为 AltiVec 的内置函数在 GCC 手册的 5.4 节中进行了介绍。(请参阅 参考资料。)向量通常需要采用新颖的方法才能形成一个好的算法,只有程序员仔细规划代码才可以实现这种功能。实际上,编写得不好的向量代码的运行速度通常比普通的代码都慢,因为它进行对齐的效率很低。VMX 寄存器中处理的数据必须按照 4 个字进行对齐(128 位),程序员要负责确保这些指令所处理的数据缓冲区都是对适当的地址进行对齐的。这需要特别注意通过在 32 位模式中动态内存分配所创建的缓冲区,因为它们只能保证是按照双字进行对齐的。然而,在 64 位模式中,malloc 子系统返回的是按照 4 个字进行对齐的地址。在线教程“Introduction to Altivec - Ten Easy Ways to Vectorize Your Code”(PDF)对代码的向量化详尽地进行了介绍。 (请参阅 参考资料。)这篇文章讨论了向量化编码对循环展开和像素操作等所带来的巨大好处。在 GCC 中,VMX 的功能是使用
-maltivec
-mabi=altivec
标记来启用的。值得注意的是,Apple 的 Mac OS X 操作系统上的 GCC 也支持了它们自己的 AltiVec 扩展的实现,但是稍有区别。区别之一是向量声明的语法,这会影响代码在这些平台之间的迁移。在 GCC for Linux on POWER 中,向量位于花括号 { } 中,而在 GCC for OS X 中,向量则是位于圆括号 ( ) 中。IBM XL C/C++ 可以同时支持这两种方法。有关这个问题以及 VMX 实现之间的差异的更多信息,请参阅 “About Compilers with VMX Support” 的 Web 主页。(请参阅 参考资料。)表 3. 向量的语法
VMX 向量语法 GCC for Linux IBM XLC C/C++ GCC for Mac OS X
花括号 {...}支持支持不支持
圆括号 (...) 不支持支持支持
对齐选项GNU toolchain for Linux on POWER 可以使用数据对齐选项来调整基于 POWER 和 PowerPC 实现(例如,嵌入式处理器)的数据宽度范围,以及与其他架构之间的互操作能力。尽管默认的对齐模式是针对 64 位的 POWER 架构进行优化的,但是实际上还可以使用一种自然的对齐选项。自然对齐方式放弃了平台上根据 long double 类型进行对齐的优点,因此是最有效的一种内存对齐方式。不过,为了保证与其他平台上编译的对象之间的互操作能力,可能会需要使用自然对齐方式。
-malign-power
标记为 POWER 架构指定优化的对齐方式,这对于 GCC 来说是默认的。
–malign-natural
标记用来指定自然对齐方式。TOC 选项POWER 处理器在执行模式中利用了一个称为 Table of Contents(简称 TOC)的概念。TOC 是每个模块的一个定位点,用作查找该模块中全局数据、静态数据以及与位置无关的代码的一个引用点。每个模块(例如,主程序或共享库)都包含有自己的 TOC。这个系统特有的属性是由 64 位的 PowerPC ELF ABI 定义的,可以使用 r2 寄存器进行访问。在构造 TOC 项时,GCC 驱动器可以接受一些选项来控制链接器的行为。这些选项会在后文中的 “GNU 链接器” 一节中进行介绍。
回页首
GNU BinutilsGNU binutils 包括一套用来构造和使用二进制文件所需要的工具。其中两个最为关键的 binutils 是 GNU 链接器 ld 和 GNU 汇编程序 as。这两个工具是 GNU 工具链中的两个完整部分,通常是由 GCC 前端进行驱动的。然而,了解如何直接引导 GNU 工具链的这些组件将非常有用。本节将介绍如何控制这两个工具并选择其他 binutils 以便易于移植,并介绍 POWER 架构特有的一些功能,以及常见的一些问题和误解。GNU 链接器链接是创建一个可执行程序的最后一个步骤。GNU 链接器可执行程序,或者称为链接编辑器,是 ld,它的角色是将对象文件合并成可执行程序,同时指定程序在运行时是如何执行的。GNU 链接器使用一个命令语言脚本来控制链接过程;默认情况下,ld 是由一组内部命令进行控制的,这些命令可以进行扩展或覆盖。强调可移植性和灵活性在 GCC 的功能中是非常明显的一条,它可以为很多不同的编译环境生成链接脚本,并向 ld 传递定制过的链接脚本,而不用手工进行干预。相反,在其他某些系统中,链接编辑器则很难实现这一点。例如,AIX 的链接器就需要自己处理定制过程,而不是在一个预链接的编译步骤中来完成。本节将介绍 GCC 驱动器与链接器之间的交互,提供 64 位 PowerPC ELF ABI 的一些详细信息,并探索 Linux on POWER 上链接器实现的一些异常之处。由于链接器的角色是将对象代码集合在一起,并产生一个可执行模块,因此编译器驱动器会将所期望的参数传递给 ld。这包括:应用程序对象文件,启动代码(在进程启动且调用 main() 之前所运行的代码),可能有用的包和所依赖的共享模块清单,库搜索路径(在链接时和调用时使用),已经平台所需要的实现特有的选项。ld 会从左到右遍历命令行,并使用这个顺序来确定如何查找/引用哪些符号。Linux on POWER 对象文件Linux on POWER 使用 ELF 对象文件格式。这种灵活且可扩展的格式可以很好地满足平台的需要,另外还有几个特殊的段。表 4 列出了这些特殊的段,并对其进行了介绍:表 4. 特殊的段
描述
.glink 包含对全局链接代码的支持。模块间的函数调用(例如主程序和 libc.so)需要加载一个函数描述符,其中这个描述符波包含了目标程序的地址和目标模块的 TOC 值。(详细信息请参看下面的 TOC。)这种机制是由过程链接表(.plt)段和 .glink 段实现的。
.toc 这是 TOC 的一部分,每个模块都有这样一个段,它是加载全局信息使用的一个字典。作为 TOC 的一部分,.toc 段包含了初始化信息。
.tocbss 其作用类似于一个 .bss 段,但是为 TOC 保存了一个尚未初始化的数据区。
.got 全局偏移量表(Global Offset Table)保存在 .got 段中,由此可以访问全局数据项(在本模块之外也是可见的)。注意,尽管数据可以加载到 .toc 或 .tocbss 段中,但是全局数据通常都是通过 GOT 进行寻址的。
.plt 包含了对模块间调用的支持。每个模块(主程序,共享对象)都包含了自己的 TOC,因此也都有自己的 TOC 定位点。这个段的内容是由动态链接器进行填充的,它支持一个用来支持惰性符号解析的简单函数描述符集合(特例)。
以下节选自“64-bit PowerPC ELF ABI Supplement”(请参阅 参考资料):ELF 处理器特有的实现通常会定义一个 GOT (‘Global Offset Table’)段用来保存位置无关的代码。有些 ELF 处理器特有的实现,包括 32 位的 PowerPC Processor Supplement,定义了一个小的数据段。有时会使用相同的寄存器来对 GOT 和这个小的数据段进行寻址。64 位的 PowerOpen ABI 定义了一个 TOC (‘Table of Contents’)段。TOC 结合了 GOT 和这个小数据段的功能。您可以看到虽然 32 位和 64 位的模块提供了相同的功能,但是它们的组织方式却是不同的。由于 64 位模块在 ELF 中引入了这个 TOC 的概念(这来自于 AIX),请考虑以下细节。内容列表正如前文中介绍的一样,每个 64 位模块都包含一个 TOC。这就意味着您的 "hello, world!" 至少包含两个模块:main 程序和 libc,因此包含两个 TOC。每个 TOC 都有一个 "知名的" TOC 定位点,这通常可以在进程运行时从寄存器 2 中找到;TOC 寄存器的值会随着执行过程从一个模块跳到另外一个模块而发生变化。这个定位点支持访问一个模块的各种全局数据的机制(例如全局的外部变量、全局静态变量以及函数描述符)。使用 TOC 意味着要使用两级间接寻址。例如,要访问一个全局变量,程序要使用 TOC 定位点(rc2)来查找指向这个变量的指针的位置。在为一个模块外部的调用查找函数描述符时,又会发生同样的操作。不过可以将数据保存在 TOC(而不是使用一个指向数据的指针),这样就避免了另外一级的间接寻找。记住,(在 64 位模式中)TOC 中保存的每个数据不管是指针还是实际数据,都必须是 8 个字节或少于 8 个字节。现在请考虑一下这对 TOC 大小的影响。TOC 相对寻址使用了一条指令,它限定于只能使用 16 位的偏移量。TOC 可以保存 65,536 个字节,在 64 位模式中,这可以用来存放 8,192 个 GOT 项。对于大型应用程序来说,您可能会看到这些空间还不够用。GNU 链接器有几个选项来处理超过 TOC 最大值的应用程序。从 2.15.90 版本的 GNU Binutils 开始,TOC 如果溢出,在链接时会自动被分隔为多个 TOC,但是对于一个特殊的结果,我们也可以使用在 表 5 中列出的选项。此处,这些选项通常都是作为 GCC 驱动程序的参数指定的。表 5. TOC 选项
TOC 选项 描述
-mfull-toc 这个选项是处理 TOC 使用的默认值。它会让链接器为可执行程序或共享对象(换而言之,就是一个模块)分配一个 TOC。如果目前的 64K 空间不足以实现链接编辑的功能,那么链接器就会报告一个错误消息说 TOC 空间已经溢出了。
-mno-fp-in-toc 这个标记可以减少 TOC 中使用的空间。通常,编译器会将浮点值直接放到 TOC 中。(AIX/GCC 开发人员可能会在自己的 32 位开发经验中见过这个选项。)这个标记可以防止将这些值保存到小数据段中,从而空出一些 TOC 空间给其他项使用。与此有关的一个标记是
no-sum-in-toc
-mno-sum-in-toc 这个标记通知 GCC 在运行时生成代码来计算一个地址和一个常量之和,而不是将它们的和放到 TOC 中。这个选项(还有
no-fp-in-toc
选项)都可以用来保留一部分 TOC 空间,但是所生成的代码更大、速度更慢。
-mminimal-toc 如果使用
no-fp-in-toc
no-sum-in-toc
标记还不能释放足够的 TOC 空间,那么就可以使用
minimal-toc
标记为每个(对象)文件生成一个单独的 TOC。这会生成很多很小的 TOC 项。虽然这解决了 TOC 溢出的问题(因为现在有无穷个 TOC 了,每个都是 64K),但是这样所生成的代码会更大、速度也更慢。使用 TOC 来指定函数地址的优点从根本上被遗弃了。
longcallPOWER 指令集提供了 bl(或称为分支链接)指令给模块内部的子程序调用使用。这种格式的指令可以使相对寻址范围达到 64MB,或 2^26(从调用位置开始计算)。然而,有时可能会达到这个限制,因此必须使用另外一种机制实现从 A 处到 B 处的寻址。
–mlongcall
选项就可以使用函数指针机制(用于模块间的调用)。换言之,每个函数调用都类似于一个模块外调用。这突破了 64M 相对地址的限制,代价是可能会稍微增加函数调用的负载。它还支持 longcall 的用法,其优先级比
-mlongcall
选项更高。
longcall (1)
会对所有后续函数声明都应用这个属性;
longcall (0)
可以停止对后续函数应用这个属性。对于开发人员来说,幸运的是 GNU for Linux on POWER 上的链接器可以快速生成需要实现这个解决方案所需要的代码。正如 AIX 链接器一样,在 64 位模式中,并不需要担心
–mlongcall
。这个特性对于 32 位的 GNU 链接器来说是不可用的,包括 SLES9 和 RHEL4。然而,在可以自由下载的 GCC 源代码中包括了这个特性。如果您有一个 32 位的应用程序在 SLES9 或 RHEL4 上运行,它调用的位置超过了 64MB 的限制,那么您就只能重新编写代码,或者将其编译为 64 位模式。由于 32 位和 64 位应用程序在 Linux on POWER 运行时是可以并存的,因此在这种情况中,我们建议您将其编译为 64 位模式。链接器脚本GNU 链接器提供了一种命令语言,可以用来控制链接编辑的操作。虽然对于那些早已熟悉 GCC 开发工具的人来说,这并没有什么奇怪;但是对于 AIX 开发人员来说,他们需要理解 AIX 和 Linux on POWER 上所存在的区别。尽管(XCOFF)对象文件的定义和 AIX 链接器的行为都是自动的,但是 GNU ld 可以对如何以及在何处合并对象文件的各个段进行更加灵活的控制。让我们来考虑一下这种脚本的基本属性。GNU ld 会自动对一个内部脚本进行操作。您可以添加或替换这些内部命令。在特定的条件下(例如,使用只出现一次的命令),必须使用定制的链接器脚本提供完整的命令集;否则,可以使用脚本为链接器添加常用的操作。在添加定制操作时,您可以在命令行中对链接器脚本简单地进行命令(链接器假设所有非对象文件都是链接器脚本)。在替换链接器默认的(内部)命令时,您可以使用
--T
--script=
选项。检查默认的链接器脚本的工作可以通过一个链接器选项发送到标准错误设备上。使用一个简单的 "hello, world" 程序,加上 verbose 选项,您就可以捕获这些内部的命令:
这会创建一个 256 行的脚本,它可以处理最常见的链接情况(我们期望如此)。AIX 开发人员应该注意这是
–bbindcmds:
选项的结果,不过我们早已说过,AIX 链接器要更加自动化。因此您可能会问:为什么会有人对这种功能感兴趣呢?有些开发工作需要使用一些 "链接器欺骗(linker trick)" 的技巧,这是另外一种声明项目对如何构建应用程序和分布内存创建约束的方法。这种需要可以通过聪明地链接编辑操作实现,GNU 链接器的命令行选项就提供了这种机制。GNU 汇编程序汇编程序的任务是接受使用人们可读的格式编写的输入文件,并生成包含机器级指令的文件。然后将一个或多个文件中的对象代码传递给链接器,后者负责生成可执行模块。GNU 汇编程序可以支持很多平台;虽然每个平台都可以使用很多命令行选项,但是也有一些平台只能支持一些系统特有的特性。与其他平台一样, GCC 驱动器可以接受使用高级语言编写的输入文件 -- 它可以产生汇编代码,然后再使用 GNU 汇编程序转换成目标代码。幸运的是,大部分开发人员都不需要直接使用汇编语言,GCC 驱动器会为开发人员隔离这些具体的实现细节。然而,当需求提高时,理解如何与汇编程序进行交互会非常有用;GCC 可以让汇编程序接受一些使用逗号分隔的选项来支持这种功能,它使用的语法为
-Wa
[选项]。例如:
这条命令使用 GCC 驱动器将文件 foo.c 编译成二进制文件 foo,并打印汇编程序的版本,即便碰到错误也是如此。虽然您可能会发现在 Linux on POWER 上,GCC、链接器、汇编程序等的用法都与其他平台非常类似,但是汇编语言本身却有很大的区别。注意一些细节问题:RISC 架构与 CISC 架构相比,通常需要多条指令来完成一个特定的任务;POWER 也不例外。如果您查看一下 GCC 所生成的汇编代码,就会注意到其中会有很多 load 和 store 指令,同时还有其他类型的指令。熟悉汇编语言的一种有用的方法是使用高级语言(例如 C)来编写代码,并使用 GCC 的
-S
选项来保存所生成的汇编文件,或者使用 objdump 对目标代码进行反汇编。二进制文件的组织在上文中有关 ld 的 “GNU 链接器” 一节中,我们曾经介绍了 ELF 对象文件的一些段;这些段就是链接器最感兴趣的地方,它们就是用来生成可执行模块的。然而,几乎编译器所生成的每个对象文件中都有这些有趣的段,它们构成了您的程序的各个部分(使用对象代码格式),如 表 6 所示,因此链接器知道如何对它们进行合并,从而创建一个程序或共享模块。表 6. 二进制文件的组织
描述
.text 可执行指令(汇编代码所转换成的指令)通常就保存在这个段中。只读常量(例如字符串常量)也可以在这个段中找到。这个平台上的文本段是只读的,这就意味着程序不能对自己进行修改;这个属性允许可执行文件的文本区可以在此程序的所有运行实例之间共享。例如,bash shell 的每个正在运行的拷贝都会共享 bash 文件的 .text 段的一份拷贝。
.data 这就是为可执行程序保存初始化过的数据的地方。从定义中我们可以看出,数据段是可读写的,进程可以对这个段中的内容(在内存中)如何操作进行完全控制。举例来说,C 语言中那些使用编译时的值进行初始化的全局变量都可以在这个段中找到。
.bss bss 段中包含了尚未初始化的数据;这个段不在对象文件中占据任何空间,但是它定义了一段内存区域,它们在运行时被清零。C 语言中那些没有给定初始化值的全局变量在程序启动时都被定义为 0;这些变量都可以在 bss 段中找到。
链接编辑器会从指定的对象文件中搜集所有的 .text 段的内容,并合并它们来创建可执行程序的代码,所有的 .data 段都被搜集起来用来创建最终的数据段,所有的 .bss 段被合并起来创建最终的 bss 段。还要注意,每个可执行模块都包含自己的段;例如,共享模块就有自己的 .text 段和 .data 段。汇编版本的 Hello, World!考虑一下这个 32 位的非 PIC 汇编版本的 "Hello, World!" 它首次出现在 Hollis Blanchard 所编写的“PowerPC assembly: Introduction to assembly on the PowerPC” 一文中(developerWorks,2002 年 7 月):清单 2. ia32 assembly
注意数据段位于最上面,其中定义了 printf 要打印的字符串 -- 它可以于 .text 段中的内容一样简单,因为它是被当作一个常量来对待的。文本段是有许多指令组成的,因为这个程序要使用几个系统调用(而不是使用 libc 中的程序,例如 printf)来完成工作。write 系统调用是在寄存器 0 中指定的,目标文件是在寄存器 3 中指定的,指向字符串的指针是在寄存器 4 中指定的,字符串的长度是在寄存器 5 中指定的。在输出字符串之后,又要将寄存器领设置为 exit 的系统调用,并传递值 "1" 作为退出代码。这个例子会被传递给汇编程序,从而创建一个对象文件;所生成的对象文件又被传递给链接器,后者生成一个可执行文件的映像。这一系列操作对于具有 AIX 和 Linux 背景的程序员来说会感觉非常熟悉。汇编中的 CFI 指令如果您发现自己要将 C++ 程序和汇编程序合并在一起,那么就可以使用 CFI(Call Frame Information)指令来使用异常处理的支持。这些指令会生成一些堆栈展开信息,这样使用汇编编写的程序就可以与使用 C++ 或其他语言编写的程序很好地结为一体了。GNU 汇编程序中所支持的 CFI 指令在“CFI support for GNU assembler (GAS)” Web 页面上进行了详细的介绍(请参阅 参考资料)。对于 Linux on POWER 来说,CFI 指令所感兴趣的是
start_proc
end_proc
。当把这些指令放到汇编代码中的每个函数两端时,就会生成 .eh_frame 信息。更多的 Binutils除了链接器和汇编程序之外,有些开发人员还会发现其他 binutils 也非常有用。在本文中我们不会讨论每个工具的功能,这在 GNU Binary Utilities 的 Web 站点上(请参阅 参考资料)已经详细介绍过了,下一节的讨论将局限于两个类似的工具。objdump 和 readelf 的出现或多或少都是非常自然的,这取决于您所使用的平台。AIX 开发人员可以认识 objdump 的风格,ELF 的老用户也早就对 readelf 很熟悉了。这两个工具在 Linux on POWER 上都可以使用。objdump 熟悉 dump 命令的 AIX 开发人员可能会希望了解有关 objdump 的知识。这个工具提供了类似的功能,而且功能比您所熟悉的功能更加丰富。objdump 的一个有用特性是可以对对象文件进行反汇编,并查看机器代码。不过,这并不适合对汇编程序进行反馈。 readelf 另外一个有用的工具是 readelf,它可以显示符号、段信息、二进制文件格式的信息等等。这在分析编译器如何从源代码创建二进制文件时非常有用,尤其是对于所链接的共享对象更是如此。AIX 开发人员会发现这与使用 dump 命令来查看所加载的段信息是一致的。
回页首
结束语Linux on POWER 上的开发与 Linux on x86 架构以及在 POWER 架构上运行的 AIX 上的开放有所不同。通常来说,这些不同对于开发人员来说并不明显,因为 GNU 软件的目标就是实现可移植性。然而,在某些情况中,需要更多信息,我们试图提供这些信息,因为它们是属于 GNU 开发工具链的,包括 GCC 编译器、GNU 链接器和汇编程序,以及其他 GNU binutils。我们已经回顾了 GNU Compiler 的功能,以及它的能力:不仅可以用来编译代码,而且可以用来控制其他 binutils。我们对链接器和汇编程序所采用的内部格式和操作进行了回顾,这重点是为了那些熟悉其他架构和操作系统的读者准备的。在本文整篇文章的内容中参考了很多其他有关该主题的资料,这些在 参考资料 中都列出了。我们在撰写本文时参考了当时最新的 GCC 手册。可能在您阅读本文时已经有了更新的发布版。请查看参考资料,获取最新的 GCC 手册。
回页首
致谢我们非常感谢 Steven Munroe、Alan Modra、Hollis Blanchard 和 David Edelsohn,以及所有对我们理解本文主题有所贡献的开发人员。尤其要感谢 Hollis,本文中使用了他的 Hello, World 的例子。
回页首
参考资料 参与论坛讨论。您可以参阅本文在 developerWorks 全球站点上的 英文原文。有关如何使用 GNU 编译器的信息,请参考 GCC 手册,其中还介绍了 GNU 编译器的特性和非兼容性以及如何报告 bug。64-bit PowerPC ELF ABI Supplement 规范中包含了 64 位 PowerPC 处理器特有的实现细节。Penguinppc.org 是 PowerPC 系列处理器的 Linux 主页。这是一个有关如何为基于 PPC 架构设置工具链的内容详尽的教程。有关向量化编码的更多信息,请参阅“Introduction to Altivec - Ten Easy Ways to Vectorize Your Code” (PDF)。有关 VMX 实现之间有何不同的信息,请参阅 About Compilers with VMX Support Web 页面。请访问 GNU Binary Utilities 的 Web 站点,其中包含了有关特定 Binutils 工具功能的详细介绍。在 IBM Processor 手册中寻找您需要的特定帮助信息。请访问 CFI support for GNU assembler (GAS) Web 页面,其中列出了 GNU 汇编程序所支持的 CFI 指令。Linux on POWER ISV Resource Center 是为那些支持和促进 Linux on POWER 平台上应用程序的独立软件开发商准备的一个内容详尽的资源。对于哪些希望开始使用 Power 架构的 Linux 开发人员来说,您会在 Linux on POWER Architecture 开发者园地中找到一些文章和资源。Hollis Blanchard 所撰写的“PowerPC assembly”(developerworks,2002 年 7 月)给出了一个 " Hello World" 例子的雏形。
回页首
作者简介
Matthew Davis 是位于德克萨斯州的奥斯汀的一名 Linux on POWER 技术顾问。他于 2000 年 5 月加入 IBM,当时他同时还在位于奥斯汀的德克萨斯大学读书。从那里,他获得了两个学位。他从事 Linux on POWER 开发社区方面的工作有差不多有 5 年的时间了,发表了二十多篇有关 Linux on Intel 和 Linux on POWER 架构的文章和论文。除了参与开源社区的开发之外,Matt 还利用业余时间在德克萨斯大学从事生命科学的研究。
 Gary R. Hook 是 IBM Solutions Development Group 的一位高级技术顾问,负责为独立软件供应商提供应用程序开发、移植和技术援助。Hook 先生的职业经历主要在基于 Unix 的应用程序开发方面。在 1990 年加入 IBM 时,他在位于德克萨斯州的 Southlake 的 AIX Technical Support 中心工作,负责为客户提供咨询和技术支持服务,重点是在 AIX 应用程序架构方面。Hook 先生现在在奥斯汀工作,在 1995 年到 2000 年期间,他是 AIX Kernel Development 团队的成员之一,专门研究 AIX 上的链接器、加载器和通用应用程序开发工具。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息