如何使用克隆系统调用分配新的TLS区域 [英] How to allocate a new TLS area with clone system call
问题描述
简短版本的问题:如果要为正在创建的线程分配新的TLS区域,我需要将什么参数传递给x86_64 Linux系统上的clone
系统调用.
Short version of question: What parameter do I need to pass to the clone
system call on x86_64 Linux system if I want to allocate a new TLS area for the thread that I am creating.
长版:
我正在做一个研究项目,为了进行一些实验,我想使用clone
系统调用而不是pthread_create
创建线程.但是,我也希望能够使用线程本地存储.我现在不打算创建多个线程,因此最好为我使用克隆系统调用创建的每个线程创建一个新的TLS区域.
I am working on a research project and for something I am experimenting with I want to create threads using the clone
system call instead of using pthread_create
. However, I also want to be able to use thread local storage. I don't plan on creating many threads right now, so it would be fine for me to create a new TLS area for each thread that I create with the clone system call.
我正在查看clone
的手册页,其中包含有关TLS参数标志的以下信息:
I was looking at the man page for clone
and it has the following information about the flag for the TLS parameter:
CLONE_SETTLS (since Linux 2.5.32)
The newtls argument is the new TLS (Thread Local Storage) descriptor.
(See set_thread_area(2).)
因此,我查看了set_thread_area
的手册页,并注意到以下内容似乎很有希望:
So I looked at the man page for set_thread_area
and noticed the following which looked promising:
When set_thread_area() is passed an entry_number of -1, it uses a
free TLS entry. If set_thread_area() finds a free TLS entry, the value of
u_info->entry_number is set upon return to show which entry was changed.
但是,经过一些实验后,看来在我的系统中未实现set_thread_area
(在x86_64平台上为Ubunut 10.04).当我运行以下代码时,出现错误消息:set_thread_area() failed: Function not implemented
However, after experimenting with this some it appears that set_thread_area
is not implemented in my system (Ubunut 10.04 on an x86_64 platform). When I run the following code I get an error that says: set_thread_area() failed: Function not implemented
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <linux/unistd.h>
#include <asm/ldt.h>
int main()
{
struct user_desc u_info;
u_info.entry_number = -1;
int rc = syscall(SYS_set_thread_area,&u_info);
if(rc < 0) {
perror("set_thread_area() failed");
exit(-1);
}
printf("entry_number is %d",u_info.entry_number);
}
我还看到,当我使用strace时,看到调用pthread_create
时会发生什么,而我看不到对set_thread_area
的任何调用.我也一直在看nptl pthread源代码,以试图了解它们在创建线程时的作用.但是我还没有完全理解它,而且我认为它比我想做的还要复杂,因为我不需要在pthread实现中具有同样强大功能的东西.我假设set_thread_area
系统调用是针对x86的,并且x86_64
使用了不同的机制.但是目前我还无法弄清楚到底是什么,所以我希望这个问题能帮助我对需要看的东西有所了解.
I also saw that when I use strace the see what happens when pthread_create
is called that I don't see any calls to set_thread_area
. I have also been looking at the nptl pthread source code to try to understand what they do when creating threads. But I don't completely understand it yet and I think it is more complex than what I'm trying to do since I don't need something that is as robust at the pthread implementation. I'm assuming that the set_thread_area
system call is for x86 and that there is a different mechanism used for x86_64
. But for the moment I have not been able to figure out what it is so I'm hoping this question will help me get some ideas about what I need to look at.
推荐答案
我正在研究一个项目,并且正在做一些试验,我想使用克隆系统调用而不是pthread_create来创建线程
I am working on a research project and for something I am experimenting with I want to create threads using the clone system call instead of using pthread_create
在不太可能发生的情况下,新线程永不调用任何libc函数(直接调用或通过调用其他调用libc的函数;这还包括动态符号解析)通过PLT),则可以将所需的任何TLS存储作为new_tls参数传递给clone
.
In the exceedingly unlikely scenario where your new thread never calls any libc functions (either directly, or by calling something else which calls libc; this also includes dynamic symbol resolution via PLT), then you can pass whatever TLS storage you desire as the the new_tls parameter to clone
.
您应该忽略对set_thread_area
的所有引用-它们仅适用于32位/ix86大小写.
You should ignore all references to set_thread_area
-- they only apply to 32-bit/ix86 case.
如果您计划计划在新创建的线程中使用libc,则应放弃您的方法:libc
期望 TLS用于以某种方式进行设置,而直接致电clone
时,您将没有 安排此类设置.当libc
发现您没有正确设置TLS时,新线程将间歇性地崩溃.调试此类崩溃非常困难,并且唯一可靠的解决方案是...使用pthread_create
.
If you are planning to use libc in your newly-created thread, you should abandon your approach: libc
expects TLS to be set up a certain way, and there is no way for you to arrange for such setup when you call clone
directly. Your new thread will intermittently crash when libc
discovers that you didn't set up TLS properly. Debugging such crashes is exceedingly difficult, and the only reliable solution is ... to use pthread_create
.
这篇关于如何使用克隆系统调用分配新的TLS区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!