第一种: gettid(), man gettid 可以看到gettid的使用方式。
使用时要先定义:_syscall0(pid_t, gettid)
其中_syscall0是一个宏(由于参数的不同还有_syscall1,_syscall2...),定义如下:
#define _syscall0(type,name) \ type name(void) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ //int 80, 软中断 : "=a" (__res) \ //输入输出都用的eax : "0" (__NR_##name)); \ //#define __NR_gettid 224 __syscall_return(type,__res); \ //返回tid }
编译时,宏展开之后,相当于定义了一个pid_t gettid(void)函数,用内嵌汇编实现,在程序中就可以使用gettid()获得线程id了。
第二种:syscall(), 名字叫syscall(),却是glibc中的库函数。 (recommend)
使用方式:syscall(__NR_gettid), 其中__NR_gettid就是224,同上。
syscall的实现要到glibc中去找,不同的硬件平台有不同的实现版本,在i386上的实现在syscall.S中:
#include <sysdep.h> .text ENTRY (syscall) PUSHARGS_6 /* Save register contents. */ _DOARGS_6(44) /* Load arguments. */ movl 20(%esp), %eax /* Load syscall number into %eax. */ ENTER_KERNEL /* Do the system call. */ POPARGS_6 /* Restore register contents. */ cmpl $-4095, %eax /* Check %eax for error. */ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ L(pseudo_end): ret /* Return to caller. */ PSEUDO_END (syscall)
eg:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #include <sys/types.h> #include <sys/syscall.h> /* must include this file */ pid_t gettid(void) { return syscall(SYS_gettid); } /* thread */ void *thread_function(void *arg) { static int i = 0; int j; i++; j = i; while (1) { printf("thread: %5u\n", gettid()); sleep(1); } } int main() { int res; pthread_t a_thread; pthread_t b_thread; void *thread_result; res = pthread_create(&a_thread, NULL, thread_function, NULL); if (res != 0) { perror("Thread creadtion failed"); exit(EXIT_FAILURE); } res = pthread_create(&b_thread, NULL, thread_function, NULL); if (res != 0) { perror("Thread creadtion failed"); exit(EXIT_FAILURE); } printf("[%d]waiting for thread to finish...\n", getpid()); pthread_join(a_thread, &thread_result); if (res != 0){ perror("Thread a join failed"); exit(EXIT_FAILURE); } printf("Thread joined, it returned %s\n", (char *)thread_result); pthread_join(b_thread, &thread_result); if (res != 0){ perror("Thread b join failed"); exit(EXIT_FAILURE); } printf("Thread joined, it returned %s\n", (char *)thread_result); exit(EXIT_SUCCESS); }
第三种:pthread_self()
同样是一个glibc提供的函数,在linux的manual中说返回的是当前线程的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,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了
相比前两种做法,这种无疑是最繁琐的,但是同理,可以获取很多glibc中维护了,但是没有提供访问方法的数据。
原文:http://blog.chinaunix.net/space.php?uid=223060&do=blog&id=2127436