日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

在linux上获得线程id的方法

發(fā)布時間:2023/12/9 linux 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在linux上获得线程id的方法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

From: http://www.linuxidc.com/Linux/2014-01/94723.htm

我使用了第二種方法,很方便:

#define gettid() syscall(__NR_gettid)

用到的地方 gettid()

在linux2.4版本后,linux使用了NPTL作為自己的線程庫,為了兼容POSIX標準,所以在內(nèi)核task中有兩個域tgid和tid,前者是進程id,后者是線程id。在linux上獲得線程id的方法,目前我所知的有三種,當然這里的三種是指在用戶態(tài)的程序中,否則除非自己寫的kernel module, 都是調(diào)用編號224的系統(tǒng)調(diào)用實現(xiàn)的(2.6版本)。?

第一種: gettid(), man gettid 可以看到gettid的使用方式。?

使用時要先定義:_syscall0(pid_t, gettid)?

其中_syscall0是一個宏(由于參數(shù)的不同還有_syscall1,_syscall2...),定義如下:

QUOTE:
#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)函數(shù),用內(nèi)嵌匯編實現(xiàn),在程序中就可以使用gettid()獲得線程id了。?

第二種:syscall(), 名字叫syscall(),卻是glibc中的庫函數(shù)。?

使用方式:syscall(__NR_gettid), 其中__NR_gettid就是224,同上。?

syscall的實現(xiàn)要到glibc中去找,不同的硬件平臺有不同的實現(xiàn)版本,在i386上的實現(xiàn)在syscall.S中:

QUOTE:
#include?
.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)


其中ENTRY也是一個宏,展開了相當?shù)拈L,主要用于在鏈接的時候讓gcc能夠"看見"并調(diào)用這段用匯編寫成的syscall()函數(shù)。?

第三種:pthread_self()?

同樣是一個glibc提供的函數(shù),在linux的manual中說返回的是當前線程的thread ID.但是實際你看到的是一個很長的,似乎沒有規(guī)律的值。什么原因得看看它的實現(xiàn):?

在glibc中,pthread_self()返回的是THREAD_SELF,這又是一個宏?

定義如下

QUOTE:
# 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的定義:

QUOTE:
struct pthread?
{?
...?
pid_t tid;?
...?
}


接下來知道怎么做了嗎?算好長度n,構(gòu)造一個假的pthread結(jié)構(gòu)。

QUOTE:
struct pthread_fake?
{?
void *nothing[n];?
pid_t tid;?
};


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

相比前兩種做法,這種無疑是最繁瑣的,但是同理,可以獲取很多glibc中維護了,但是沒有提供訪問方法的數(shù)據(jù)。

總結(jié)

以上是生活随笔為你收集整理的在linux上获得线程id的方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。