gettid 和pthread_self的区别

2019-07-13 08:59发布

    Linux中,每个进程有一个pid,类型pid_t,由getpid()取得。Linux下的POSIX线程也有一个id,类型 pthread_t,由pthread_self()取得,该id由线程库维护,其id空间是各个进程独立的(即不同进程中的线程可能有相同的id)。Linux中的POSIX线程库实现的线程其实也是一个进程(LWP),只是该进程与主进程(启动线程的进程)共享一些资源而已,比如代码段,数据段等。
linux多线程环境下gettid() pthread_self() 两个函数都获得线程ID,可它们的返回值不一样。
linux使用进程模拟线程,gettid 函数返回实际的进程ID(内核中的线程的ID).
pthread_self 函数返回 pthread_create创建线程时的ID(POSIX thread ID).

为什么有两个thread ID:       线程库实际上由两部分组成:内核的线程支持+用户态的库支持(glibc)。Linux在早期内核不支持线程的时候,glibc就在库中(用户态)以线程(就是用户态线程)的方式支持多线程了。POSIX thread只对用户编程的调用接口作了要求,而对内核接口没有要求。linux上的线程实现就是在内核支持的基础上,以POSIX thread的方式对外封装了接口,所以才会有两个ID的问题。

在glibc中,pthread_self()返回的是THREAD_SELF,这是一个宏。其定义如下
# define THREAD_SELF
({ struct pthread *__self;
asm ("movl %%gs:%c1,%0" : "=r" (__self)
: "i" (offsetof (struct pthread, header.self)));
__self;})

    这段代码返回了当前线程的descriptor(即struct pthread结构,pthread_self()得到的就是这个descriptor的地址, 也就是unsigned long int类型的pthread_t。知道了这一点就好办了,找到thread descriptor的定义:
  struct pthread
{
...
pid_t tid;
...
}

接下来知道怎么做了吗?算好长度n,构造一个假的pthread结构。
  struct pthread_fake
{
void *nothing[n];
pid_t tid;
};

用(struct pthread_fake *) pthread_self()->tid得到线程id了。





The man page for gettid says:


The thread ID returned by this call is not the same thing as a POSIX thread ID(i.e., the opaque value returned by pthread_self(3)).