如何将pthread_t映射到pid(在Linux上)

10

有没有一种明智的方法将 pthread_create()std::thread::native_handle() 返回的 pthread_t 值映射到 Linux 中的 pid(tid)?在有人重复提交之前,这与查找线程自身的pid(tid)无关(可以使用gettid()实现)。

疯狂的方法是以某种方式强制线程调用gettid()并传递结果,但那太麻烦了。

我心中可能的一个应用是将程序创建的线程(其中可用pthread_t)与ps -T提供的输出进行协调。


4
据我所知,在Linux中,pthread_t是指向struct pthread的指针,该结构体有一个成员变量 tid。但我不知道任何可接受的方法来读取这个信息。如果您有可用的调试符号,可以在gdb中使用ptype pthread来检查这个结构体。仅限于调试目的,您可以使用p &((pthread*)0)->tid来读取 tid 的偏移量,然后在程序本身中使用此偏移量来读取 pthread_t 中的 tid。或者,您可以使用某些dwarf reader库从符号文件本身中读取偏移量,以实现“可移植性”。 - geza
@geza 真的非常有趣,感谢您提供这些信息! - SergeyA
一对重复问题 证据A 证据B - n. m.
这是一个 hack,pthread 应该不能映射到操作系统 tid,但抽象层泄漏了。 - n. m.
实际上,做“疯狂”的部分并不太难。sigaction + pthread_sigqueue + 一个函数(或std::function)在info->si_value.sival_ptr中+条件变量=通用阻塞executeOnThread(id,func)实现的构建块。然后,您可以使用它来构建参数化版本的gettid和任何其他线程相关函数(例如backtrace,getrusage等)。如果您还使用C ++,则lambda和变量捕获有助于平滑传递参数,但这只是为了方便,您显然可以在C中执行相同的操作。 - idij
显示剩余3条评论
3个回答

5

pthread_t 映射到 tid 的一种方法(复杂、不可移植、仅适用于Linux,会轻微破坏)而不查看 struct pthread 是:

  1. 使用 pthread_setname_np 将线程名称设置为唯一的内容。
  2. 迭代 /proc/self/task 子目录并从每个子目录中读取名为 comm 的文件中的一行。
  3. 如果该行等于刚刚使用的唯一字符串,则从子目录名称的最后一个组件中提取 tid。 这就是你的答案。

操作系统不使用线程名称,因此更改它应该是安全的。 但是,您可能希望将其设置回原始值(使用 pthread_getname_np 获取它)。


事实上,我的线程已经有了名称,因此这种方法值得考虑。接受。 - SergeyA
@SergeyA,你能分享一下你是如何使用pthread_setname_np实现你的目标的吗? - hago

1
在Linux上实现此操作的某种hacky方法是使用process_vm_readv系统调用。如果您知道pthread_t,请使用它将内存从远程进程复制到本地缓冲区,然后将指针转换为struct pthread并检索tid字段的值。

-1

Pthreads是POSIX线程。

在pthread_t中,根据您的架构,typedef为某种类型的长整型。实际上,它是一个指针类型转换为内部结构pthread,如上所述。

故意不返回struct pthread是有意义的。线程高度依赖于底层操作系统。并非所有Unix风格的操作系统都实现了相同的线程。我甚至不相信gettid是一个POSIX函数,我认为它是Linux特定的。

您可以查看glibc / nptl源代码以获取Linux特定实现的struct pthread。请参见https://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/descr.h;h=fdeb397eab94730a5dab3181abcdae815ed6914e;hb=48a8f8328122ab8d06b7333cb87be46feeaf7cca

但我相信你要找的是 getpid。它是进程 ID 而不是线程 ID。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接