SET_THREAD_AREA - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-02-09
名称
get_thread_area,set_thread_area-处理线程本地存储信息
语法
#include <linux/unistd.h> #if defined __i386__ || defined __x86_64__ # include <asm/ldt.h> int get_thread_area(struct user_desc *u_info); int set_thread_area(struct user_desc *u_info); #elif defined __m68k__ int get_thread_area(void); int set_thread_area(unsigned long tp); #elif defined __mips__ int set_thread_area(unsigned long addr); #endif
注意:这些系统调用没有glibc包装器。请参阅注释。
说明
这些调用为线程本地存储实现提供特定于体系结构的支持。目前,set_thread_area()在m68k,MIPS和x86(32位和64位变体)上都可用; get_thread_area()在m68k和x86上可用。
在m68k和MIPS上,set_thread_area()允许在与调用线程关联的内核数据结构中存储任意指针(在m68k的tp参数和MIPS的addr参数中提供)。以后可以使用get_thread_area()检索此指针(有关在MIPS上获取线程指针的信息,另请参见注释)。
在x86上,Linux将三个全局描述符表(GDT)条目专用于线程本地存储。有关GDT的更多信息,请参阅《英特尔软件开发人员手册》或《 AMD体系结构编程手册》。
这两个系统调用都使用一个参数,该参数是指向以下类型结构的指针:
struct user_desc { unsigned int entry_number; unsigned int base_addr; unsigned int limit; unsigned int seg_32bit:1; unsigned int contents:2; unsigned int read_exec_only:1; unsigned int limit_in_pages:1; unsigned int seg_not_present:1; unsigned int useable:1; #ifdef __x86_64__ unsigned int lm:1; #endif };
get_thread_area()读取由u_info-> entry_number指示的GDT条目,并填写u_info中的其余字段。
set_thread_area()在GDT中设置TLS条目。
set_thread_area()设置的TLS数组条目对应于用户传递的u_info-> entry_number的值。如果此值是有界的,则set_thread_area()将u_info指向的TLS描述符写入线程的TLS数组中。
当将set_thread_area()传递给entry_number -1时,它将搜索一个空闲的TLS条目。如果set_thread_area()找到了空闲的TLS条目,则在返回时设置u_info-> entry_number的值以显示更改了哪个条目。
如果将read_exec_only和seg_not_present设置为1并且所有其他字段均为0,则user_desc被视为"空"。如果将"空"描述符传递给set_thread_area(),则将清除相应的TLS条目。有关其他详细信息,请参见错误。
从Linux 3.19开始,尽管清除段还是可以接受的,但是不能使用set_thread_area()写入不存在的段,16位段或代码段。
返回值
在x86上,这些系统调用成功返回0,失败返回-1,并正确设置errno。
在MIPS和m68k上,set_thread_area()始终返回0。在m68k上,get_thread_area()返回线程区域指针值(以前是通过set_thread_area()设置的)。
错误说明
- EFAULT
- u_info是无效的指针。
- EINVAL
- u_info->entry_number超出范围。
- ENOSYS
- get_thread_area()或set_thread_area()作为64位系统调用被调用。
- ESRCH
- (set_thread_area())找不到免费的TLS条目。
版本
set_thread_area()首次出现在Linux 2.5.29中。 get_thread_area()首次出现在Linux 2.5.32中。
遵循规范
set_thread_area()和get_thread_area()是特定于Linux的,不应在打算移植的程序中使用。
备注
Glibc不为这些系统调用提供包装器,因为它们通常仅供线程库使用。如果您想直接调用它们,请使用syscall(2)。
arch_prctl(2)可能会干扰x86上的set_thread_area()。有关更多详细信息,请参见arch_prctl(2)。这通常不是问题,因为arch_prctl(2)通常仅由64位程序使用。
在MIPS上,可以使用以下指令获取线程区域指针的当前值:
rdhwr dest,
该指令捕获并由内核处理。
BUGS
在Linux 3.19之前的64位内核上,如果设置了user_desc中的填充位之一,则将防止描述符被视为空(请参见modify_ldt(2))。结果,清除TLS条目的唯一可靠方法是使用memset(3)将整个user_desc结构(包括填充位)清零,然后设置read_exec_only和seg_not_present位。在Linux 3.19上,除了entry_number以外,完全由零组成的user_desc也将被解释为清除TLS条目的请求,但是在较早的内核上,其行为有所不同。
在Linux 3.19之前,DS和ES段寄存器不得引用TLS条目。
另外参见
arch_prctl(2),modify_ldt(2),ptrace(2)(PTRACE_GET_THREAD_AREA和PTRACE_SET_THREAD_AREA)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。