在 Linux 上,TLS 是由内核还是由 libc(或其他语言运行时)设置的?
On Linux, is TLS set up by the kernel or by libc (or other language runtime)?
我正在研究如何在 Linux 系统上实现 TLS(线程本地存储)。文档 ELF Handling for Thread-Local Storage 解释了如何将程序对线程局部变量的要求编码为 ELF 二进制文件,以及 "runtime" 应如何处理此类二进制文件。
但是,我不清楚实际上设置 TLS 区域的 "runtime" 是 Linux 内核(及其加载 ELF 二进制文件的代码)还是某些libc 中的初始化代码。有人可以简单解释一下吗?
(背景:我正在尝试静态地-link 和 运行 一个应用程序,但它在启动时出现段错误。在 gdb 中,我可以看到段错误代码是来自 libc 的一些初始化代码。它试图使用相对于 GS 的地址读取静态变量,但 GS 为零。)
线程本地存储初始化是 libc 提供的启动代码的一部分。当静态 linking 时,您的 linker 应该将 TLS 初始化添加到启动代码 linked 到您的程序中。
例如,glibc 在 libc.a
中有 __libc_setup_tls
和 _dl_tls_setup
(以及其他相关内容),如果您 link 通过,比方说,gcc -static
。 (对于动态 linked 程序,_dl_
... 函数是 ELF 动态 linker-loader ld-linux.so
的一部分,它不用于 运行 静态 linked 程序。)
因此,静态 linked 可执行文件中正确的 TLS 初始化是 C 库(提供代码)和工具链(必须了解如何正确 link 在所有必要的启动代码中)。
内核对 TLS 初始化的参与很小。 (基本上,它只需要确保 .tdata
部分可用于 libc 进行初始化。)有关详细信息,请参阅 ELF file TLS and LOAD program sections。
我正在研究如何在 Linux 系统上实现 TLS(线程本地存储)。文档 ELF Handling for Thread-Local Storage 解释了如何将程序对线程局部变量的要求编码为 ELF 二进制文件,以及 "runtime" 应如何处理此类二进制文件。
但是,我不清楚实际上设置 TLS 区域的 "runtime" 是 Linux 内核(及其加载 ELF 二进制文件的代码)还是某些libc 中的初始化代码。有人可以简单解释一下吗?
(背景:我正在尝试静态地-link 和 运行 一个应用程序,但它在启动时出现段错误。在 gdb 中,我可以看到段错误代码是来自 libc 的一些初始化代码。它试图使用相对于 GS 的地址读取静态变量,但 GS 为零。)
线程本地存储初始化是 libc 提供的启动代码的一部分。当静态 linking 时,您的 linker 应该将 TLS 初始化添加到启动代码 linked 到您的程序中。
例如,glibc 在 libc.a
中有 __libc_setup_tls
和 _dl_tls_setup
(以及其他相关内容),如果您 link 通过,比方说,gcc -static
。 (对于动态 linked 程序,_dl_
... 函数是 ELF 动态 linker-loader ld-linux.so
的一部分,它不用于 运行 静态 linked 程序。)
因此,静态 linked 可执行文件中正确的 TLS 初始化是 C 库(提供代码)和工具链(必须了解如何正确 link 在所有必要的启动代码中)。
内核对 TLS 初始化的参与很小。 (基本上,它只需要确保 .tdata
部分可用于 libc 进行初始化。)有关详细信息,请参阅 ELF file TLS and LOAD program sections。