加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux – 线程本地存储变量的地址

发布时间:2020-12-13 23:11:21 所属栏目:Linux 来源:网络整理
导读:好吧,说我有 __thread int myVar; 然后我将 myVar从一个线程传递到另一个线程……如果数据真的是“本地”,那么1个线程的TLS存储可能无法映射到其他线程的地址空间,事实上,你可能会认为它不应该.这会导致SIGSEGV或其他东西.但是,系统可以将相同的地址映射到不
好吧,说我有

__thread int myVar;

然后我将& myVar从一个线程传递到另一个线程……如果数据真的是“本地”,那么1个线程的TLS存储可能无法映射到其他线程的地址空间,事实上,你可能会认为它不应该.这会导致SIGSEGV或其他东西.但是,系统可以将相同的地址映射到不同的页面.这是Linux用.tbss / .tdata做的吗?在这种情况下,传递变量的地址将为您提供错误变量的地址!您将获得自己的本地副本,而不是您尝试传递的副本.或者,是否所有内容都共享并映射到不同的虚拟地址 – 允许您传递__thread vars的地址?

显然,应该通过传递其地址来尝试将线程本地存储传递到另一个线程来殴打和鞭打.还有一百万种其他方式 – 例如复制到任何其他变量!但是,如果有人知道,我很好奇.

>官方描述了这种情况下的行为
>目前的GCC / Linux实施细节

– 埃文

解决方法

至少对于x86,使用段寄存器执行TLS.默认段寄存器%ds隐含在寻址存储器的指令中.当访问TLS时,线程使用另一个段寄存器 – %gs用于i386,%fs用于x86-64 – 在调度线程时保存/恢复,就像其他寄存器在上下文切换中一样.

因此,可以通过以下方式访问流程范围的变量:

mov (ADDR) -> REG ; load memory `myVar` to REG.

这隐含着:

mov %DS:(ADDR) -> REG

对于TLS,编译器生成:

mov %FS:(ADDR) -> REG ; load thread-local address `myVar` to REG.

实际上,即使变量的地址在不同的线程中看起来是相同的,例如,

fprintf(stdout,"%pn",& myVar); /* in separate threads... */

事实上,每个线程对段寄存器使用不同的值,这意味着它们映射到物理存储器的不同区域.如果要将地址从一个线程传递到另一个线程,则无法访问它在第一个线程中表示的内存 – 另一个段寄存器值在第二个线程中生效.

Windows使用相同的方案(它可以交换%fs和%gs的角色 – 不确定)和OS X.对于其他架构,ELF ABI有一个深入的technical guide到TLS.它缺少对ARM体系结构的讨论,并且有关于IA-64和Alpha的详细信息,因此它显示了它的年龄.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读