首页 kernel正文

线程种的gettid和pthread_self区别

helight0 kernel 2013-04-22 51 0

这几天写程序老是使用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的结构,也就是一个独立的调度单元。

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。