问题描述
||
我曾遇到过这样一种情况:在两个处理器之间对glibc / syscall的多次调用(其中一个是通过使用CLONE_VM调用clone()创建的)最终将导致我的程序崩溃。
根据我的理解,如果我打算使用CLONE_VM t,则还必须指定CLONE_SETTLS。
谁能给我一个例子,说明如何为我的新克隆准备TLS存储以及如何使用CLONE_SETTLS实际执行clone()调用吗?
解决方法
下面加上一粒盐,因为我只看了“编译过程中”(这里没有木剑)。
Glibc / NPTL使用TLS来存储很多线程状态。 TLS指向每个线程“ 0”(“ 1”可能表示pthread描述符),该线程在“ 2”处的线程本地堆栈中分配,从“ 3”调用。
在x86中,
struct pthread
的第一个成员是ѭ5should,它应指向struct user_desc
(其条目号可能在体系结构之间以及内核版本之间有所不同,我系统上的glibc使用6作为其内部TLS)。 tcb
作为自变量传递给do_clone()
。
如果仔细查看这些功能,您会发现glibc在TLS上存储了很多信息:有关线程本地堆栈的信息,该程序是否有多个线程,健壮的互斥锁列表,线程启动例程及其参数,pthread属性标志,排程政策...
总而言之,如果您可以摆脱真正的pthread线程的困扰,它将更加简单。
, 另一种方法是先呼叫clone
,然后呼叫pthread_create
。
通过这种方式,您正在使用线程库来获取正确的TLS(位于线程堆栈上)。
示例代码:
int tmp_run(void *arg) {
void *ret;
pthread_t thread;
// now call the wanted function
pthread_create(&thread,NULL,run,arg);
pthread_join(thread,&ret);
return (long) ret;
}
int main(...) {
...
int clone_pid = clone (tmp_run,stack,flags arg);
...
}
如果需要对线程属性进行更多控制(例如,堆栈位置),请查看pthread_create。