對於Linux線程,也許大家並不陌生,而我們通常所說的線程是指基於POSIX標准的線程,而Linux下除了兼容POSIX標准,而且提供線程在內核級的支持。
早在Linux kernel2.4之前,Linux的線程(LinuxThread)屬於用戶級,內核根本不知道線程的存在,為了得到內核的支持,2003 年,RedHat公司(很了不起的一個公司)發布了NPTL(Native POSIX Thread Library),至今廣泛使用。
NPTL很優秀,對信號的處理是按照每進程的原則進行的;getpid() 會為所有的線程返回相同的進程 ID。例如,如果發送了 SIGSTOP 信號,那麼整個進程都會停止;使用 LinuxThreads,只有接收到這個信號的線程才會停止。這樣可以在基於 NPTL 的應用程序上更好地利用調試器,例如 GDB。
額外話說多了,下面具體看看下面如何獲得線程的ID吧!
經常我們需要在程序一個線程中獲得這個線程的id,有人會說,可以通過pthread_create函數傳遞參數傳入,等主線程創建子線程成功,那麼這個pid會自動賦值
#define TNUM 2
struct BN
{
pthread_t pid;
int N;
};
void *run(void *args)
{
BN *recive = (BN *)args;
cout << "pid: " << recive->pid << endl;
return (void *)(recive->N);
}
int main(int c, char *v[])
{
int i;
int ret;
char *result;
pthread_t pid[TNUM];
BN bn[TNUM];
for (i = 0; i < TNUM; i ++)
{
bn[i].pid = pid[i];
bn[i].N = mN;
ret = pthread_create(&pid[i], NULL, run, &bn[i]);
//...出錯處理
}
return 0;
}
難題是主線程去分配子線程id的時刻,run函數並不能很確切的知道,所以當讀取recive->pid時,就會產生錯誤;
正確的方法應該使用pthread_self()函數來獲得POSIX的線程id,此函數調用內部進制直到pid分配完成。
有人會問,獲取進程id的函數不是getpid(),獲取線程id的函數不是gettid()麼?
這裡與剛才前面所說的有些關系,目前gettid獲得的pid是需要系統調用(syscall)的,這個syscall返回的pid不是上面所說的POSIX線程id,這個是內核的線程id,具體調用的方式如下:
pid_t pid = syscall(SYS_gettid);
或
pid_t pid = syscall(__NR_gettid);
或
//僅限於i386,如果是x86_64,則調用186
pid_t pid = syscall(224);
以往舊的方式syscallx的調用已經被廢棄。
看到這裡,也許有人會問,pid_t和pthread_t可以相互轉換麼?一個是POSIX的線程、一個是內核的線程?如果你感興趣在這方面研究的話,可以不妨試試,答案肯定是可以的。
至此,你看完這篇文章,明白了Linux線程id怎麼獲得了麼?