Solaris Studio C 支持编译能与标准 C 库链接并在包含标准 C 库和其他运行时支持库的运行时环境中执行的程序。C 标准中为此类环境指明了一个托管环境。而为未提供标准库函数的环境指明了一个独立式环境。
针对于独立式环境,一般情况下 C 编译器不支持编译,因为某些可能从编译代码中调用的运行时支持函数一般仅在标准 C 库中可用。问题是:编译器转换的源代码可能将调用引入至不包含函数调用的源代码结构中的运行时支持函数中,并且这些函数一般在独立式的环境中不可用。请看以下示例:
% cat -n lldiv.c 1 void 2 lldiv( 3 long long *x, 4 long long *y, 5 long long *z) 6 { 7 *z = *x / *y ; 8 } % cc -c -m32 lldiv.c % nm lldiv.o | grep " U " 0x00000000 U __div64 % cc -c -m64 lldiv.c % nm lldiv.o | grep " U " |
在该示例中,使用 -m32 选项编译源文件 lldiv.c 使其在 32 位平台上运行时,对第 7 行中声明的转换将导致外部引用名为 __div64 的运行时支持函数,并且此函数是 32 位版本的标准 C 库中唯一可使用的函数。
使用 -m64 选项编译同一源文件使其在 64 位平台上运行,编译器将使用目标计算机中的 64 位算法指令集,但其中不包括 64 位版本的标准 C 库中运行时支持函数所需要的指令。
尽管在一般情况下不支持使用 C 编译器将独立式环境视为目标,但在遵从注意事项的情况下可使用此编译器在特定的独立式环境(即 Solaris 内核和设备驱动程序)中编译代码。
必须写入在 Solaris 内核中运行的代码(包括设备驱动程序),这样外部函数调用才能引用那些只在内核中可用的函数。要使以上情况成为可能,建议遵从以下准则:
对于只在用户模式下运行的库,不要包含头文件。
除非确定内核中存在与标准 C 库或其他用户模式库中相同的函数,否则不要调用这些函数。
不要使用浮点类型或 C99 复合类型。
不要使用与运行时支持库相关联的编译选项,例如 -xprofile 和 -xopenmp。
cc(1) 手册页的“文件”一节中介绍了与特定编译器选项关联的可重定位对象文件。相关选项的说明下面介绍了与 C 编译器选项关联的运行时支持库。
如前所述,在源代码转换后,编译器可能会生成对运行时支持函数的调用。对于 Solaris 内核,在特定情况下可能被调用的运行时支持函数集要小于一般情况下调用的相应函数集,因为内核不使用浮点/复合类型、数学库函数或与运行时支持库相关联的编译器选项。
下表列出了 C 编译器转换源代码后,可能被调入代码中的运行时支持函数,这些代码是为了能够在 Solaris 内核中运行而编译的。该表列出了其上的源代码转换生成了调用的平台、被调用函数的名称,以及导致生成函数调用的原结构或编译器功能。仅列出了 64 位平台,因为支持 C 编译器的所有版本的 Solaris 均在 64 位内核中运行。
针对于 32 位指令集进行编译时,可能会因指令集的特定限制而调用特定于其他计算机的支持函数。
功能 |
64 位平台 |
引用自 |
---|---|---|
__align_cpy_n |
SPARC |
返回大结构;n 取值为1、2、4、8 或 16 |
_memcpy |
x86 |
返回大结构 |
_memcpy |
x86 和 SPARC |
矢量化 |
_memmove |
x86 和 SPARC |
矢量化 |
_memset |
x86 和 SPARC |
矢量化 |
注意:一些内核的版本不提供 _memmove()、_memcpy() 或 _memset(),但提供与用户模式例程相似的内核模式例程,例如 memmove()、memcpy() 和 memset()。
可在《编写设备驱动程序》指南和《SPARC 遵从性定义》(版本 2.4)中找到其他信息。