线程种的gettid和pthread_self区别

这几天写程序老是使用thread来做,所以自己封装了一个threadbase的类来做简单的测试使用,但是在写的过程种发现又两个获取线程id的函数:pthread_self和gettid,那这两个函数有什么区别呢?

看gettid的man,这样写道:
gettid() returns the caller’s thread ID (TID). In a single-threaded process, the thread ID is equal to the process ID
(PID, as returned by getpid(2)). In a multithreaded process, all threads have the same PID, but each one has a unique
TID. For further details, see the discussion of CLONE_THREAD in clone(2).

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)).

而pthread_self的man这样写:

Thread IDs are only guaranteed to be unique within a process. A thread ID may be reused after a terminated thread has

been joined, or a detached thread has terminated.

The thread ID returned by pthread_self() is not the same thing as the kernel thread ID returned by a call to get‐
tid(2).

现在可以大体知道pthread_self是为了区分同一进程种不同的线程,而gettid获取的线程id和pid是有关系的。

写个程序检测一下:

void ThreadTest::Entry()
{
while (IsRun())
{
printf(“ThreadTest is runing…pid:%d—ttid:%ld—self:0x%x\r\n”,
getpid(), syscall(SYS_gettid), pthread_self());
Sleep(1000);
};
}

int main(int argc, char* argv[])
{
int num = 3;
ThreadTest testhread[num];
for (int i = 0; i < num; i++) testhread[i].Start(); while (1) { printf("main loop ...... pid:%d---ttid:%ld---self:0x%x\r\n", getpid(), syscall(SYS_gettid), pthread_self()); sleep(10); }; } 输出: main loop ...... pid:2822---ttid:2822---self:0xb7439b50 ThreadTest is runing...pid:2822---ttid:2824---self:0xb6c36b70 ThreadTest is runing...pid:2822---ttid:2825---self:0xb6435b70 ThreadTest is runing...pid:2822---ttid:2823---self:0xb7437b70 ps的结果 ps -eLf |grep threadtest|grep -v grep UID PID PPID LWP C NLWP STIME TTY TIME CMD helight 2822 4315 2822 0 4 17:32 pts/0 00:00:00 ./threadtest helight 2822 4315 2823 0 4 17:32 pts/0 00:00:00 ./threadtest helight 2822 4315 2824 0 4 17:32 pts/0 00:00:00 ./threadtest helight 2822 4315 2825 0 4 17:32 pts/0 00:00:00 ./threadtest 运行两个进程 helight@zhwen:/data/code/xcode/xlib/thread$ ps -eLf |grep threadtest|grep -v grep helight 2838 4315 2838 0 4 17:35 pts/0 00:00:00 ./threadtest helight 2838 4315 2839 0 4 17:35 pts/0 00:00:00 ./threadtest helight 2838 4315 2840 0 4 17:35 pts/0 00:00:00 ./threadtest helight 2838 4315 2841 0 4 17:35 pts/0 00:00:00 ./threadtest helight 2885 2842 2885 0 4 17:35 pts/5 00:00:00 ./threadtest helight 2885 2842 2886 0 4 17:35 pts/5 00:00:00 ./threadtest helight 2885 2842 2887 0 4 17:35 pts/5 00:00:00 ./threadtest helight 2885 2842 2888 0 4 17:35 pts/5 00:00:00 ./threadtest 从这里看一看到这个gettid获取的线程id有可能就是进程id,也就是所说的主线程。 看代码: pthread_self是在gblic中实现: helight@zhwen:/data/kernel/glibc-2.17$ vim nptl/pthread_self.c pthread_t __pthread_self (void) { return (pthread_t) THREAD_SELF; } /* Return the thread descriptor for the current thread. The contained asm must *not* be marked volatile since otherwise assignments like pthread_descr self = thread_self(); do not get optimized away. */ # define THREAD_SELF \ ({ struct pthread *__self; \ asm ("movl %%gs:%c1,%0" : "=r" (__self) \ : "i" (offsetof (struct pthread, header.self))); \ __self;}) 看到获取的就是这个pthread结构体中的header.self, helight@zhwen:/data/kernel/glibc-2.17$ vim nptl/pthread_create.c versioned_symbol (libpthread, __pthread_create_2_1, pthread_create, GLIBC_2_1); struct pthread *pd = NULL; ..... pd->header.self = pd;

可以看到这个获取的就是线程控制模块(tcb)的地址,也就是pthread_self的返回值。

再来看gettid的实现,这个是在内核中实现的,我下了2.6.32的内核来看

helight@zhwen:/data/kernel/linux-2.6.32$ vim kernel/timer.c

系统调用在这里

/* Thread ID – the internal kernel “pid” */
SYSCALL_DEFINE0(gettid)
{
return task_pid_vnr(current);
}

include/linux/sched.h

static inline pid_t task_pid_vnr(struct task_struct *tsk)
{
return __task_pid_nr_ns(tsk, PIDTYPE_PID, NULL);
}

nr = pid_nr_ns(task->pids[type].pid, ns);

这里看到其实就是pid,所以linux中的线程在内核种都是task_struct的结构,也就是一个独立的调度单元。