歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux下獲得線程ID syscall(224)

對於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怎麼獲得了麼?

Copyright © Linux教程網 All Rights Reserved