0

我知道 和之间的区别。生成一个 POSIX 线程 ID,它由通常定义为. 我们可以用来获取生成的线程的IDpthread_self()syscall(SYS_gettid)pthread_create()unsigned long intpthread_selfpthread_create

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

实际上,有时我发现一个linux线程ID映射到同一个进程中的多个POSIX线程ID,这意味着通过调用产生一对POSIX线程ID和linux线程ID后pthread_create(),POSIX线程ID发生变化,而linux线程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)

的调用者21根据linux线程ID(12848)的结果,但是它们有不同的POSIX线程ID。1和也是如此5

这是拦截代码片段。

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;
}
4

1 回答 1

1

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

是的。

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


通常定义为

pthread_t是不透明的。也不要对它的实现方式做任何假设。


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

真的吗?我对此表示怀疑。至少如果所有相关的 POSIX 线程 ID 都有效,即相关线程尚未加入,或者如果运行分离,则线程尚未结束。

于 2017-10-20T07:05:50.023 回答