每个 TLS 引用都遵循下列访问模型之一。这些模型按照最常见、但最少优化到速度最快、但限制最大的顺序列出。
此模型允许从共享目标文件或动态可执行文件中引用所有 TLS 变量。如果是第一次从特定线程引用 TLS 块,此模型还支持延迟分配此块。
此模型是对 GD 模型的优化。编译器可能会确定变量在要生成的目标文件中是局部绑定或受到保护的。在这种情况下,编译器将指示链接编辑器静态绑定动态的 tlsoffset 并使用此模型。与 GD 模型相比,此模型可提供更好的性能。每个函数只需要调用一次 tls_get_addr() 即可确定 dtv0,m 的地址。进行链接编辑时绑定的动态 TLS 偏移会与每个引用的 dtv0,m 地址相加。
此模型只能引用初始静态 TLS 中包含的 TLS 变量。此模板由进程启动时可用的所有 TLS 块和一个小的备份预留空间组成。请参见程序启动。在此模型中,给定变量 x 相对于线程指针的偏移存储在 x 的 GOT 项中。
此模型可以从初始进程启动后通过延迟装入、过滤器或 dlopen(3C) 装入的共享库中引用有限数量的 TLS 变量。该访问可通过固定的备份预留空间来实现。此预留空间只能为未初始化的 TLS 数据项提供存储空间。为实现最大的灵活性,共享目标文件应使用动态的 TLS 模型引用线程局部变量。
此模型只能引用动态可执行文件的 TLS 块中包含的 TLS 变量。链接编辑器静态地计算相对于线程指针的偏移,而不需要进行动态重定位或额外引用 GOT。此模型不能用于引用动态可执行文件外部的变量。
链接编辑器可以将代码从更常规的访问模型转换为更优化的模型(如果确定适合进行转换)。这种转换可以使用独特的 TLS 重定位来实现。这些重定位不仅请求执行更新,还会标识要使用的 TLS 访问模型。
链接编辑器在了解 TLS 访问模型和要创建的目标文件类型后,便可执行转换。例如,如果一个可重定位目标文件使用 GD 访问模型,被链接到一个动态可执行文件中。在这种情况下,链接编辑器可以适当地使用 IE 或 LE 访问模型转换引用。然后执行模型所需的重定位。
下图说明了不同的访问模型,以及从一个模型到另一个模型的转换。
图 14-2 线程局部存储的访问模型和转换