Thread Local Storage (TLS) 实现探究

Thread Local Storage (TLS) 实现探究

💡 原文中文,约30700字,阅读约需73分钟。
📝

内容提要

本文探讨了glibc 2.31版本中线程局部存储(TLS)的实现,包括通过%fs寄存器访问TLS变量,以及不同TLS模型(如local exec、initial exec、local dynamic和global dynamic)的优化和使用场景。每种模型的实现方式和性能开销不同,动态链接器负责管理TLS空间的分配和访问。

🎯

关键要点

  • 本文探讨了glibc 2.31版本中线程局部存储(TLS)的实现。
  • TLS是线程局部存储的缩写,可以存储每个线程的数据。
  • 使用__thread标记全局变量以存储在TLS中,每个线程都有一份。
  • 不同TLS模型包括local exec、initial exec、local dynamic和global dynamic,性能开销不同。
  • 动态链接器负责管理TLS空间的分配和访问。
  • TLS的组织方式是每个线程都有一个buffer来保存TLS数据,使用%fs寄存器来维护。
  • 可执行程序和动态库的TLS需求在启动时由动态链接器分配TLS空间。
  • dlopen动态加载的动态库需要独立的TLS空间,使用dtv数组记录TLS空间的起始地址。
  • 编译器和链接器协同工作以优化TLS模型的使用,选择最优的实现方法。
  • 四种TLS模型的对比显示,越通用的模型运行时开销越大。
  • 实际编程中,TLS模型的选择取决于编译器和链接器的策略。

延伸问答

什么是线程局部存储(TLS)?

线程局部存储(TLS)是一种用于存储每个线程独立数据的机制,确保每个线程都有自己的数据副本。

glibc 2.31版本中TLS的实现方式是什么?

glibc 2.31版本通过%fs寄存器访问TLS变量,并使用不同的TLS模型来优化性能,包括local exec、initial exec、local dynamic和global dynamic。

不同的TLS模型有什么区别?

不同的TLS模型在性能开销和使用场景上有所不同,local exec模型开销最小,适用于可执行程序访问自身的TLS变量,而global dynamic模型则适用于不确定来源的TLS变量。

如何在C语言中使用TLS?

在C语言中,可以使用__thread关键字标记全局变量,使其存储在TLS中,每个线程都有独立的副本。

动态链接库如何管理TLS空间?

动态链接库通过动态链接器在加载时分配TLS空间,并使用dtv数组记录TLS空间的起始地址,以便在运行时访问。

TLS的性能开销如何影响编程选择?

在编程中,TLS模型的选择会影响性能,编译器和链接器会根据上下文选择最优的TLS模型,以减少运行时开销。

➡️

继续阅读