Posix线程ID与linux线程ID有一对一的关系吗?

时间:2017-10-20 06:19:10

标签: c linux multithreading pthreads linuxthreads

我知道pthread_self()syscall(SYS_gettid)之间的differencepthread_create()生成一个POSIX线程ID,它由struct pthread_t表示,通常定义为unsigned long int。我们可以使用pthread_self来获取pthread_create生成的ID of the thread

使用strace,我知道libpthread.so.0中的pthread_create()是通过调用clone系统调用来实现的,这也是用于fork()的系统调用。通过调用pthread_create()创建POSIX线程后,将生成一个新的POSXI线程(由pthread_self()返回的线程ID标识)和一个新的linux线程(由syscall(SYS_gettid)返回的线程ID标识) 。这是否意味着POSIX线程ID与linux线程ID具有一对一的关系?它们分别代表pthread_tpid_t

的主题

实际上,有时我发现一个linux线程ID在同一进程中映射到多个POSIX线程ID,这意味着在通过调用pthread_create()生成一对POSIX线程ID和linux线程ID后,POSIX线程当linux线程ID保持不变时,ID会发生变化。有没有办法在保持linux线程ID不变的同时更改POSIX线程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 ... 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)
  4. 根据linux线程ID(12848),2的调用者是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;
    }
    

1 个答案:

答案 0 :(得分:1)

  

Posix线程ID是否与linux线程ID具有一对一的关系

但请考虑这是一个实现细节。其他操作系统可能会以不同的方式执行此操作。

  

通常定义为

{{1}}不透明。同样不要对它的实现方式做任何假设。

  

我发现一个linux线程ID映射到几个POSIX线程ID

真的?我怀疑这一点。至少不是如果所讨论的所有POSIX线程ID都有效,那么相关线程尚未加入,或者如果运行分离,则线程尚未结束。