Linux线程ID是32位的,对于linux中线程id的讨论

1d13be22bfe8df58aa785bd41cbab156.png

在LINUX系统中,POSIX threads库提供了pthread_t来标识一个线程,通过pthread_self()可以得到,如下:

#include

#include

using namespace std;

void* thread_func(void*)

{

//pthread_t other_thread_id = pthread_self();

//cout << "other_thread_id=" << other_thread_id << endl;

return NULL;

}

int main(int argc, char *argv[])

{

pthread_t t1, t2;

pthread_create(&t1, NULL, thread_func, NULL);

cout << t1 << endl;

pthread_join(t1, NULL);

//pthread_create(&t2, NULL, thread_func, NULL);

//cout << t2 << endl;

//pthread_join(t2, NULL);

return 0;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

得到结果:

typedef unsigned long int pthread_t;

这个数值很大。而且比较两个线程是否相同也需要用pthread_equal(pthread_t t1, pthread_t t2)来比较。

那么,使用pthread_t来标识线程id是否是最合适的?

答案是否

原因:这个pthread_t的值很大,无法作为一些容器的key值。

pthread_t是由POSIX pthread库内部提供的,只在进程内部有意义,无法关联操作系统的任务调度之类的信息。比方说在/proc查找不到关于pthread_t得到的task。

glibc的Pthreads实现实际上把pthread_t作为一个结构体指针,指向一块动态分配的内存,但是这块内存是可以反复使用的,也就是说很容易造成pthread_t的重复。也就是说pthreads只能保证同一进程内,同一时刻的各个线程不同;不能保证同一个进程全程时段每个线程具有不同的id,不能保证线程id的唯一性。下面可以通过一个例子:

#include

#include

using namespace std;

void* thread_func(void*)

{

//pthread_t other_thread_id = pthread_self();

//cout << "other_thread_id=" << other_thread_id << endl;

return NULL;

}

int main(int argc, char *argv[])

{

pthread_t t1, t2;

pthread_create(&t1, NULL, thread_func, NULL);

cout << t1 << endl;

pthread_join(t1, NULL);

pthread_create(&t2, NULL, thread_func, NULL);

cout << t2 << endl;

pthread_join(t2, NULL);

return 0;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

运行结果:

上述原因显然表明pthread_t是不适合作为线程的标识的。所以应该使用什么来标识呢。

首先对于进程id,有函数getpid返回的pid_t来标识。那么线程有没有类似的gettid来标识呢。

在LINUX系统中,建议使用gettid系统调用的返回值作为线程id,这么做的原因:

返回值是一个pid_t,其值是一个很小的整数,方便输出。

在linux系统中,它直接标识内核任务调度id,可通过/proc文件系统中找到对应项:/proc/tid 或者 /proc/pid/task/tid,方便定位到具体线程

任何时刻都是唯一的,并且由于linux分配新的pid采用递增轮回办法,短时间内启动多个线程也会具有不同的id

0是非法值,操作系统第一个进程init的pid是1

glibc没有封装这个gettid,需要我们手动封装。

举例:

#include

#include

#include //获取线程id的系统调用头文件

#include

#include

using namespace std;

void* thread_func(void*)

{

//获取线程id的系统调用

cout << syscall(__NR_gettid) << endl;

return NULL;

}

int main(int argc, char *argv[])

{

pthread_t t1, t2;

pthread_create(&t1, NULL, thread_func, NULL);

cout << t1 << endl;

pthread_join(t1, NULL);

pthread_create(&t2, NULL, thread_func, NULL);

cout << t2 << endl;

pthread_join(t2, NULL);

return 0;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

结果:

和pthread_t的描述完全不一样。

使用比较优雅的方式是定义一个gettid的宏

#include //获取线程id的系统调用头文件

#include

#include

//定义宏

#define gettid() syscall(__NR_gettid)

1

2

3

4

5

6

验证TID是否正确的方法:

查看进程pid

(1) ps ux | grep prog_name

(2) pgrep prog_name

查看线程tid

(1) ps -efL | grep prog_name

(2) ls /proc/pid/task

————————————————

版权声明:本文为CSDN博主「ZgZeQi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/zeqi1991/article/details/81611919

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值