Oracle® Solaris 11.2 链接程序和库指南

退出打印视图

更新时间: 2014 年 7 月
 
 

线程局部存储节

编译时分配的线程局部数据的独立副本必须与各个执行线程关联。要提供此数据,应使用 TLS 节指定大小和初始内容。编译环境在 SHF_TLS 标志标识的节中分配 TLS。这些节根据存储的声明方式提供已初始化的 TLS 和未初始化的 TLS。

  • 已初始化的线程局部变量分配在 .tdata.tdata1 节中。此初始化可能需要重定位。

  • 未初始化的线程局部变量定义为 COMMON 符号。最终分配在 .tbss 节中进行。

在分配了任何已初始化的节后会立即分配未初始化的节,并进行填充以便正确对齐。合并的节一起构成 TLS 模板,每次创建新线程时,都会使用此模板分配 TLS。此模板的已初始化部分称为 TLS 初始化映像。所有因已初始化的线程局部变量而生成的重定位将应用于此模板。当新线程需要初始值时,将使用重定位的值。

TLS 符号的符号类型为 STT_TLS。这些符号被指定了相对于 TLS 模板开头的偏移。与这些符号关联的实际虚拟地址与此无关。地址仅指向模板,而不指向每个数据项的每线程副本。在动态可执行文件和共享目标文件中,对于已定义符号,STT_TLS 符号的 st_value 字段包含指定的 TLS 偏移。对于未定义的符号,此字段包含零。

定义了多个重定位以支持访问 TLS。请参见线程局部存储的重定位类型线程局部存储的重定位类型线程局部存储的重定位类型。通常,TLS 重定位引用 STT_TLS 类型的符号。TLS 重定位还可以引用与 GOT 项关联的局部节符号。在这种情况下,指定的 TLS 偏移存储在关联的 GOT 项中。

对于根据 TLS 项进行的重定位,重定位地址在 TLS 模板的末尾编码为负偏移。计算该偏移时,首先将模板大小舍入到 32 位目标文件中最接近的 8 字节边界,然后舍入为 64 位目标文件中最接近的 16 字节边界。此舍入操作确保静态 TLS 模板合理对齐以便可用于任何用途。

在动态可执行文件和共享目标文件中,PT_TLS 程序项用于描述 TLS 模板。此模板包含以下成员:

表 14-1  ELF PT_TLS 程序头项
成员
p_offset
TLS 初始化映像的文件偏移
p_vaddr
TLS 初始化映像的虚拟内存地址
p_paddr
0
p_filesz
TLS 初始化映像的大小
p_memsz
TLS 模板的总大小
p_flags
PF_R
p_align
TLS 模板的对齐方式