我可以从pthread_self()获取线程的堆栈地址吗?

时间:2012-01-04 15:31:05

标签: c linux gcc pthreads x86-64

我想通过一些函数获取线程的堆栈地址,我们可以传递给 pthread_self()。可能吗?我这样做的原因是因为我想为其堆栈中的某个线程编写我自己分配的线程标识符。我可以写在堆栈的末尾附近(堆栈内存的末尾而不是当前的堆栈地址。我们可以预期应用程序不会到达堆栈的底部,因此从那里使用空间)。

换句话说,我想使用线程堆栈来放置一种线程局部变量。那么,我们是否有类似pthread提供的以下功能?

stack_address = stack_address_for_thread( pthread_self() );

为了这个目的,我可以使用gcc的线程局部变量的语法,但是我处于不能使用它们的情况。

4 个答案:

答案 0 :(得分:6)

可能最好使用pthread_key_createpthread_key_getspecific并让实施担心这些细节。

使用的一个很好的例子是:

pthread_key_create

编辑:我应该澄清一下 - 我建议你使用libpthread提供的创建线程本地信息的方法,而不是通过将一些东西推到堆栈的末端来滚动你自己的东西,在那里你的信息可能会丢失。

答案 1 :(得分:2)

使用GCC,使用__thread关键字声明线程局部变量更简单,例如

  __thread int i;
  extern __thread struct state s;
  static __thread char *p;

这是GCC特定的(但我猜clang也有,并且最新的C ++和未来的C标准有类似的东西),但比基于upeon pthread_self()的指针黑客更不易碎(并且应该比pthread_key_getsspecificsuggested by Denniston

更快,但更不便携

但我真的希望你在问题中提供更多背景和动力。

答案 2 :(得分:2)

  

我想为线程编写自己指定的线程标识符

有多种方法可以实现这一目标。最明显的一个:

__thread int my_id;
  

为了这个目的,我可以使用gcc的线程局部变量的语法,但是我遇到了无法使用它们的情况。

您需要解释为什么您不能使用线程本地。很可能其他解决方案(例如pthread_getattr_np)也无效。

答案 3 :(得分:-2)

首先获取堆栈的底部,并使用以下代码为其提供读/写权限。

pthread_attr_t attr;
void * stackaddr;
int * plocal_var;
size_t stacksize;

pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack( &attr, &stackaddr, &stacksize );

printf( "stackaddr = %p, stacksize = %d\n", stackaddr, stacksize );

plocal_var = (int*)mmap( stackaddr, 4096, PROT_READ | PROT_WRITE, 
          MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0 );
// Now try to write something 
*plocal_var = 4;

然后你可以获得线程ID,函数 get_thread_id()如下所示。请注意,调用大小为4096的mmap会导致堆栈边界推动4096,这就是我们在获取局部变量地址时减去4096的原因。

int get_thread_id()
{
    pthread_attr_t attr;
    char * stackaddr;
    int * plocal_var;
    size_t stacksize;

    pthread_getattr_np(pthread_self(), &attr);
    pthread_attr_getstack( &attr, (void**)&stackaddr, &stacksize );

    //printf( "stackaddr = %p, stacksize = %d\n", stackaddr, stacksize );

    plocal_var = (int*)(stackaddr - 4096);

    return *plocal_var;
}