链接程序和库指南

程序装入(特定于处理器)

系统创建或扩充进程映像时,系统会以逻辑方式将文件的段复制到虚拟内存段。系统以物理方式读取文件的时间和可能性取决于程序的执行行为、系统负载等。

除非进程在执行过程中引用了逻辑页,否则进程不需要物理页。进程通常会保留许多页面不对其进行引用。因此,延迟物理读取可以提高系统性能。要实际达到这种效率,可执行文件和共享库文件必须具有文件偏移和虚拟地址同余(以页面大小为模数)的段映像。

32 位段的虚拟地址和文件偏移对模数 64 K (0x10000) 同余。64 位段的虚拟地址和文件偏移对模数 1 MB (0x100000) 同余。通过将各段与最大页面大小对齐,无论物理页大小如何,文件都适合进行换页。

缺省情况下,64 位 SPARC 程序与 0x100000000 的起始地址链接。整个程序位于 4 GB 上的地址空间内,包括其文本、数据、堆、栈和共享库依赖性。这有助于确保 64 位程序正确,因为如果程序截断其任何指针,则程序在其最低有效的 4 GB 地址空间中将出现错误。尽管 64 位程序在 4 GB 上的地址空间内进行链接,但仍可以使用 mapfile 和链接编辑器的 -M 选项,链接 4 GB 以下的地址空间内的程序。 请参见 /usr/lib/ld/sparcv9/map.below4G

下图显示了 SPARC 版本的可执行文件。

图 7–8 SPARC: 可执行文件(64 K 对齐)

SPARC 可执行文件布局示例。

下表定义了上图中可装入段的各元素。

表 7–28 SPARC: ELF 程序头段(64 K 对齐)

成员 

文本 

数据 

p_type

PT_LOAD

PT_LOAD

p_offset

0x0

0x4000

p_vaddr

0x10000

0x24000

p_paddr

未指定 

未指定 

p_filesize

0x3a82

0x4f5

p_memsz

0x3a82

0x10a4

p_flags

PF_R + PF_X

PF_R + PF_W + PF_X

p_align

0x10000

0x10000

下图显示了 x86 版本的可执行文件。

图 7–9 32 位 x86: 可执行文件(64 K 对齐)

x86 可执行文件布局示例。

下表定义了上图中可装入段的各元素。

表 7–29 32 位 x86: ELF 程序头段(64 K 对齐)

成员 

文本 

数据 

p_type

PT_LOAD

PT_LOAD

p_offset

0x0

0x4000

p_vaddr

0x8050000

0x8064000

p_paddr

未指定 

未指定 

p_filesize

0x32fd

0x3a0

p_memsz

0x32fd

0xdc4

p_flags

PF_R + PF_X

PF_R + PF_W + PF_X

p_align

0x10000

0x10000

此示例的文件偏移和虚拟地址以文本和数据的最大页面大小为模数同余。根据页面大小和文件系统块大小,最多可有四个文件页包含混合文本或数据。


注 –

前面的示例反映了对其文本段取整的典型的 Solaris 系统二进制文件。


数据段结尾要求对未初始化的数据进行特殊处理,系统将其定义为从零值开始。如果文件的最后一个数据页包含不属于逻辑内存页的信息,则必须将无关数据设置为零,而不是设置为可执行文件的未知内容。

其他三个页面中的混合内容在逻辑上不属于进程映像。没有指定系统是否会清除这些混合内容。以下各图中显示了此程序的内存映像,假定页面大小为 4 KB (0x1000)。为简单起见,这些图仅对一种页面大小进行说明。

图 7–10 32 位 SPARC: 进程映像段

SPARC 进程映像段示例。

图 7–11 x86: 进程映像段

x86 进程映像段示例。

可执行文件和共享库在段装入的某个方面有所不同。可执行文件段通常包含绝对代码。为使进程正确执行,段必须位于用于创建可执行文件的虚拟地址处。系统会使用未更改的 p_vaddr 值作为虚拟地址。

另一方面,共享库段通常包含与位置无关的代码。使用此代码,段的虚拟地址在不同进程之间会进行更改,而不会使执行行为无效。

尽管系统会为各个进程选择虚拟地址,但仍会保持各段之间的相对位置。由于与位置无关的代码在各段之间使用相对地址,因此内存中虚拟地址之间的差值必须与文件中虚拟地址之间的差值匹配。

以下各表显示针对多个进程可能指定的共享库虚拟地址,从而说明了固定的相对位置。此外,这些表中还包括基本地址计算。

表 7–30 32 位 SPARC: ELF 共享库段地址示例

源 

文本 

数据 

基本地址 

文件 

0x0

0x4000

0x0

进程 1 

0xc0000000

0xc0024000

0xc0000000

进程 2 

0xc0010000

0xc0034000

0xc0010000

进程 3 

0xd0020000

0xd0024000

0xd0020000

进程 4 

0xd0030000

0xd0034000

0xd0030000

表 7–31 32 位 x86: ELF 共享库段地址示例

源 

文本 

数据 

基本地址 

文件 

0x0

0x4000

0x0

进程 1 

0x8000000

0x8004000

0x80000000

进程 2 

0x80081000

0x80085000

0x80081000

进程 3 

0x900c0000

0x900c4000

0x900c0000

进程 4 

0x900c6000

0x900ca000

0x900c6000

程序的解释程序

启动动态链接的动态可执行文件或共享库可以包含一个 PT_INTERP 程序头元素。在 exec(2) 过程中,系统将从 PT_INTERP 段检索路径名,并通过解释程序文件段创建初始进程映像。解释程序负责从系统接收控制并为应用程序提供环境。

在 Solaris OS 中,解释程序称为运行时链接程序,即 ld.so.1(1)