问题描述
我使用 glibc-2.27
追踪了 GDB
。在 178
中的 sysdeps/unix/sysv/linux/getsysstats.c
行,存在一个 thread local storage
访问权限,如下所示:
while (l < re && isspace (*l))
IIUC,isspace()
似乎访问一个表 映射 ASCII
字符到符号类型,以快速确定当前字符是否为空格或不。这个表似乎是一个TLS
。相关拆解如下:
0x7f8f9ef480de <__GI___get_nprocs+318> mov 0x2cbd1b(%rip),%rax # 0x7f8f9f213e00
0x7f8f9ef480e5 <__GI___get_nprocs+325> mov %fs:(%rax),%rdi
rax
包含 0xffffffffffffff98
,IIUC 表示 每个线程的表地址,使用以下公式计算等式:$fs_base + 0xffffffffffffff98
。当我使用这个等式来查找每个线程的表地址时,它们都返回相同值,0x00007f8f9732b82c
。如下图所示:
(gdb) thread apply all x/2x $fs_base + 0xffffffffffffff98
Thread 47 (Thread 22457.22471):
0x7f8f75dfc698: 0x9732b82c 0x00007f8f
Thread 46 (Thread 22457.22470):
0x7f8f768fd698: 0x9732b82c 0x00007f8f
Thread 45 (Thread 22457.22469):
0x7f8f773fe698: 0x9732b82c 0x00007f8f
Thread 44 (Thread 22457.22468):
0x7f8f77eff698: 0x9732b82c 0x00007f8f
Thread 43 (Thread 22457.22467):
0x7f8f80a53698: 0x9732b82c 0x00007f8f
Thread 37 (Thread 22457.22465):
0x7f8f81c55698: 0x9732b82c 0x00007f8f
Thread 36 (Thread 22457.22464):
0x7f8f82456698: 0x9732b82c 0x00007f8f
Thread 35 (Thread 22457.22463):
0x7f8f8e6b0698: 0x9732b82c 0x00007f8f
Thread 34 (Thread 22457.22461):
0x7f8f8f480698: 0x9732b82c 0x00007f8f
Thread 33 (Thread 22457.22460):
0x7f8f94824698: 0x9732b82c 0x00007f8f
Thread 32 (Thread 22457.22459):
0x7f8f9649f698: 0x9732b82c 0x00007f8f
Thread 31 (Thread 22457.22458):
0x7f8f96ea0698: 0x9732b82c 0x00007f8f
Thread 30 (Thread 22457.22457):
0x7f8fa2570a18: 0x9732b82c 0x00007f8f
Thread 29 (Thread 22457.22466):
0x7f8f81454698: 0x9732b82c 0x00007f8f
我认为 TLS
对每个线程独占,但是,在这里,所有线程使用相同的 变量位于 0x00007f8f9732b82c
。为什么会这样?似乎链接器识别变量是read-only
并节省一些空间?
解决方法
您已经证明每个线程都有一个不同的指针变量,在 TLS 存储中 0x7f8f75dfc698
与 0x7f8f768fd698
等
它们都指向同一个表的事实是完全正常的,除非您使用 uselocale(3)
在不同的线程中有不同的语言环境。
我认为 glibc 具有用于不同语言环境的静态常量 (.section .rodata
) 字符映射表,并且它根据语言环境设置了一个指向正确表的指针。为每个线程复制整个表将非常低效,浪费更多 L3 缓存占用空间。如果要这样做,您会期望整个表就在那里,没有间接级别。
看看 glibc 如何实现 isupper()
之类的函数 - 通过索引字符属性标志数组,并检查该数组元素中的某个位。 (即每个数组元素都是一个标志位图)。
https://code.woboq.org/userspace/glibc/ctype/ctype.h.html 和相同目录中的相关 .c 文件。