2017-10-20 121 views
0

我知道pthread_self()syscall(SYS_gettid)之間的differencepthread_create()產生一個POSIX線程ID,它由一個struct pthread_t表示,它通常被定義爲一個unsigned long int。我們可以使用pthread_self來獲得pthread_create生成的ID of the threadPosix線程ID與linux線程ID是否有一對一的關係?

隨着strace,我知道pthread_create()在libpthread.so.0是通過調用clone系統調用,這也是用於fork()系統調用來實現。通過調用pthread_create()創建POSIX線程後,會生成一個新的POSXI線程(由pthread_self()返回的線程ID標識)和一個新的Linux線程(由線程標識由syscall(SYS_gettid)返回)。這是否意味着POSIX線程ID與linux線程ID具有一對一的關係?它們分別代表pthread_tpid_t的線程?

實際上,有時我發現一個linux線程ID在同一個進程中映射到多個POSIX線程ID,這意味着在通過調用pthread_create()產生一對POSIX線程ID和linux線程ID後,POSIX線程ID改變linux線程ID保持不變。有沒有辦法改變POSIX線程ID,同時保持linux線程ID不變?如果有,那pthread函數是什麼?

謝謝。

這裏是通過攔截forkpthread_create調用的日誌。 ltid表示linux線程ID,tid表示POSIX線程ID,pid表示進程ID。

1 message: fork pid:12832 ltid:12832 tid:140300035462976  child pid:12848 ltid:12848 tid:140300035462976 

2 message: fork pid:12848 ltid:12848 tid:140549640255296  child pid:12849 ltid:12849 tid:140549640255296 

3 message: fork pid:12848 ltid:12848 tid:140549640255296  child pid:12850 ltid:12850 tid:140549640255296 

4 message: fork pid:12848 ltid:12848 tid:140549640255296  child pid:12851 ltid:12851 tid:140549640255296 

5 message: pthread_create pid:12848 ltid:12848 tid:139968995022656  child ltid:12865 tid:139968995018496 

6 message: pthread_create pid:12848 ltid:12865 tid:139968995018496  child ltid:12865 tid:139968933345024 

7 message: fork pid:12832 ltid:12832 tid:140300035462976  child pid:12885 ltid:12885 tid:140300035462976 

8 message: fork pid:12885 ltid:12885 tid:139870512949056  child pid:12886 ltid:12886 tid:139870512949056 

我的解釋:

  1. (PID = 12832,程序ltid = 12832,TID = 140 ... 976)調用fork生產(PID = 12848,程序ltid = 12848,TID = 140 .. 0.976)
  2. (PID = 12848,的ltid = 12848,TID = 140 ...... 296)調用fork產生(PID = 12849,的ltid = 12849,TID = 140 ...... 296)
  3. (PID = 12848 ,ltid = 12848,tid = 139 ... 656)調用pthread_create生成(ltid = 12865,tid = 139 ... 496)

2的調用者是根據linux線程ID(12848)的1的結果,但它們具有不同的POSIX線程ID。 15也是如此。

這是攔截代碼片段。

void *intermedia(void * arg){ 

    struct thread_param *temp; 

    void *(*start_routine) (void *); 
    temp=(struct thread_param *)arg; 

    char test[1024]=""; 
    sprintf(test,"child ltid:%ld\ttid:%lu\n",syscall(SYS_gettid),pthread_self()); 
    log_message(test) 

    return temp->start_routine(temp->args);  
} 


int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg){ 
    static void *handle = NULL; 
    static P_CREATE old_create=NULL; 
    if(!handle) 
    { 
     handle = dlopen("libpthread.so.0", RTLD_LAZY); 
     old_create = (P_CREATE)dlsym(handle, "pthread_create"); 
    } 
    pthread_t tmp=pthread_self(); 
    char test[1024]=""; 
    sprintf(test,"pthread_create pid:%d\tptid:%ld\ttid:%lu\n",getpid(),syscall(SYS_gettid),tmp); 
    log_message(test); 

    struct thread_param *temp=malloc(sizeof(struct thread_param)); 
    temp->args=arg; 
    temp->start_routine=start_routine; 

    int result=old_create(thread,attr,intermedia,(void *)temp); 

    return result; 
} 

pid_t fork(void){ 
    static void *handle = NULL; 
    static FORK old_fork=NULL; 
    if(!handle) 
    { 
     handle = dlopen("libc.so.6", RTLD_LAZY); 
     old_fork = (FORK)dlsym(handle, "fork"); 
    } 

    char test[1024]=""; 
    sprintf(test,"fork pid:%d\tltid:%ld\ttid:%lu\t",getpid(),syscall(SYS_gettid),pthread_self()); 

    pid_t ppid=getpid(); 
    pthread_t ptid=pthread_self(); 
    pid_t result=old_fork(); 
    if(result==0){ 
     sprintf(test,"%s\tchild pid:%d\tltid:%ld\ttid:%lu\n",test,getpid(),syscall(SYS_gettid),pthread_self()); 
     log_message(test); 
    } 
    return result; 
} 
+0

標記「linuxthreads」在上下文中似乎是錯誤的,因爲「linuxthreads」與POSIX線程不同。 – alk

+0

@alk這是否意味着Linux內核線程?如果不合適,我可以刪除這個標籤。 – Chalex

+0

關於在Linux上進行線程化的歷史:http://www.drdobbs.com/open-source/nptl-the-new-implementation-of-threads-f/184406204(閱讀可能會使不同的字眼清晰) – alk

回答

1

不POSIX線程ID與Linux的線程ID

是一個一比一的關係。

但請考慮這個實現細節。其他操作系統可能會做這個不同。


其通常被定義爲

pthread_t是不透明的。也不要對它的實現做任何假設。


我發現有一個Linux的線程ID映射到多個POSIX線程ID

真的嗎?我懷疑這一點。至少不是所有POSIX線程ID都是有效的,也就是說相關線程還沒有被加入,或者如果運行分離,線程還沒有結束。

+0

他們在我的測試案例中都是有效的。因爲我攔截了所有的'pthread_create()'調用來記錄線程之間的父子關係。 – Chalex

+0

@Chalex:敢於展示測試用例的代碼? – alk

+0

它們在我的測試用例中都是有效的。因爲我攔截了所有的'pthread_create()'調用來記錄線程之間的父子關係。我發現線程具有相同的linux線程標識,但是不同的POSIX線程標識全部調用'pthread_create()',這意味着它們被執行。 – Chalex