• glibc 里的线程 id


            这里讲的是通过 pthread_create() 函数返回的线程 id,其实就是 glibc 库里维护的线程id,它跟内核维护的线程 id 不一样,pthread_create() 返回的线程 id 并不一定是唯一的。我们看 pthread_create 函数的源码,它最后返回的线程 id 是什么样的?

    1. //...............................
    2. /* Check for valid priorities. */
    3. int minprio = INTERNAL_SYSCALL (sched_get_priority_min, scerr, 1,
    4. iattr->schedpolicy);
    5. int maxprio = INTERNAL_SYSCALL (sched_get_priority_max, scerr, 1,
    6. iattr->schedpolicy);
    7. if (pd->schedparam.sched_priority < minprio
    8. || pd->schedparam.sched_priority > maxprio)
    9. {
    10. /* Perhaps a thread wants to change the IDs and if waiting
    11. for this stillborn thread. */
    12. if (__builtin_expect (atomic_exchange_acq (&pd->setxid_futex, 0)
    13. == -2, 0))
    14. lll_futex_wake (&pd->setxid_futex, 1, LLL_PRIVATE);
    15. __deallocate_stack (pd);
    16. return EINVAL;
    17. }
    18. }
    19. /* Pass the descriptor to the caller. */
    20. *newthread = (pthread_t) pd;
    21. LIBC_PROBE (pthread_create, 4, newthread, attr, start_routine, arg);
    22. /* Start the thread. */
    23. return create_thread (pd, iattr, STACK_VARIABLES_ARGS);
    24. }

    函数就是通过参数 newthread 返回的线程 id,实现里直接把 pd 强转成 pthread_t 类型赋值给了 newthread。这个 pd 是什么类型呢?

    1. int
    2. __pthread_create_2_1 (newthread, attr, start_routine, arg)
    3. pthread_t *newthread;
    4. const pthread_attr_t *attr;
    5. void *(*start_routine) (void *);
    6. void *arg;
    7. {
    8. STACK_VARIABLES;
    9. const struct pthread_attr *iattr = (struct pthread_attr *) attr;
    10. if (iattr == NULL)
    11. /* Is this the best idea? On NUMA machines this could mean
    12. accessing far-away memory. */
    13. iattr = &default_attr;
    14. struct pthread *pd = NULL;
    15. int err = ALLOCATE_STACK (iattr, &pd);
    16. if (__builtin_expect (err != 0, 0))
    17. /* Something went wrong. Maybe a parameter of the attributes is
    18. invalid or we could not allocate memory. Note we have to
    19. translate error codes. */
    20. return err == ENOMEM ? EAGAIN : err;

    struct pthread 是一个结构体,记录线程信息的:

    所以这个线程 id 就是一个地址(被强转成pthread_t,也就是 unsigned long int 类型值)值?用 GDB 看一下最清楚了:

    这个 pd 指针的值就是 0x7ffff7fd8700,而这个值也是结构体里数据的首地址:

     

    所以这个地址值转成 unsignd long int 是多少呢?强转后的十进制值就是 140737353975552。

     

     

    就是执行程序里打印的线程 id。 所以 pthread_create() 返回的线程 id,其实就是保存线程信息的结构体的首地址。因此这个线程 id 是很重要的,其他线程相关函数可以通过这个 id 访问线程信息,如 pthread_t 强转为 struct pthread* 类型,其实 thread_id 就是一个地址:

    1. int
    2. pthread_getattr_np (thread_id, attr)
    3. pthread_t thread_id;
    4. pthread_attr_t *attr;
    5. {
    6. struct pthread *thread = (struct pthread *) thread_id;
    7. struct pthread_attr *iattr = (struct pthread_attr *) attr;
    8. int ret = 0;
    9. lll_lock (thread->lock, LLL_PRIVATE);
    10. /* The thread library is responsible for keeping the values in the
    11. thread desriptor up-to-date in case the user changes them. */
    12. memcpy (&iattr->schedparam, &thread->schedparam,
    13. sizeof (struct sched_param));
    14. iattr->schedpolicy = thread->schedpolicy;
    15. /* Clear the flags work. */
    16. iattr->flags = thread->flags;
    17. /* The thread might be detached by now. */
    18. if (IS_DETACHED (thread))
    19. iattr->flags |= ATTR_FLAG_DETACHSTATE;
    20. /* This is the guardsize after adjusting it. */
    21. iattr->guardsize = thread->reported_guardsize;

    这个函数就是获取指定线程的信息,其中当然包括用户设置的栈大小

    所以要获取线程栈大小,需要使用两个函数调用:

     pthread_getattr_np(pthread_self(), &attr)

    pthread_attr_getstacksize(&attr, &stack_size) 

  • 相关阅读:
    华为政企管理软件产品集
    ASP.NET Core - 配置系统之配置添加
    就是一整个爱住,你们大胆飞,我就是最坚强的后盾——Java面试突击宝典
    小学数学深度教学论文
    Audified U73b压缩器和U78饱和器发布升级版
    劣币驱良币的 pacing 之殇
    精研科技融入汽车内饰 Laedana打造车内空间新生态
    亲手将TP-LINK路由器改装成交换机使用
    GBASE 8s 自动删除正在被使用的数据库
    C++中的字符串编码处理
  • 原文地址:https://blog.csdn.net/tianyexing2008/article/details/134246947