【问题标题】:How can you get the Linux thread Id of a std::thread()如何获取 std::thread() 的 Linux 线程 ID
【发布时间】:2013-03-29 18:13:42
【问题描述】:

我在玩std::thread,我想知道如何获得新std::thread() 的线程ID,我不是在谈论std::thread::id,而是给线程的操作系统ID(你可以使用pstree查看它)。 这只是为了我的知识,它只针对 Linux 平台(不需要是可移植的)。

我可以像这样在线程中获取 Linux 线程 ID:

#include <iostream>
#include <thread>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>

void SayHello()
{
    std::cout << "Hello ! my id is " << (long int)syscall(SYS_gettid) << std::endl;
}

int main (int argc, char *argv[])
{
    std::thread t1(&SayHello);
    t1.join();
    return 0;
}

但是如何在主循环中检索相同的 id 呢?我没有找到使用std::thread::native_handle 的方法。我相信有可能通过pid_t gettid(void); 得到它,因为 c++11 实现依赖于 pthreads,但我一定是错的。

有什么建议吗? 谢谢。

【问题讨论】:

  • std::thread::native_handle() 有什么问题?
  • @AndyProwl - native_handle()native_handle_type 不需要存在,如果它们确实存在,那么您可以对结果对象执行的操作是实现定义的。 没有可移植语义。也许特定的实现支持这样做,但这是用户和库文档之间的问题。
  • @AndyProwl 它返回的值与std::thread::id 相同。
  • @PeteBecker:我明白这一点,但我假设 OP 可以做一些不可移植的事情(因为他专门针对一个平台),我希望实现能够提供这样的基本信息.我知道不需要提供,但如果不提供,我会觉得很奇怪。

标签: c++ multithreading c++11 pthreads


【解决方案1】:

假设您使用的是 GCC 标准库,std::thread::native_handle() 返回由 pthread_self() 返回的 pthread_t 线程 ID,而不是由 gettid() 返回的操作系统线程 ID。 std::thread::id() 是同一个 pthread_t 的包装器,而 GCC 的 std::thread 没有提供任何获取操作系统线程 ID 的方法,但您可以创建自己的映射:

std::mutex m;
std::map<std::thread::id, pid_t> threads;
void add_tid_mapping()
{
  std::lock_guard<std::mutex> l(m);
  threads[std::this_thread::get_id()] = syscall(SYS_gettid);
}
void wrap(void (*f)())
{
  add_tid_mapping();
  f();
}

然后创建你的线程:

std::thread t1(&wrap, &SayHello);

然后通过以下方式获取 ID:

pid_t tid = 0;
while (tid == 0)
{
  std::lock_guard<std::mutex> l(m);
  if (threads.count(t1.get_id()))
    tid = threads[t1.get_id()];
}

【讨论】:

  • 哦,这样获取 id 很聪明,太好了,谢谢!
  • 你为什么要建立一个std::map? syscall() 预计会这么贵吗?此外,您似乎从未从映射中删除线程,这可能被视为内存泄漏(例如,在网络服务器设置中,随着时间的推移会产生许多线程,并且进程通常会运行数月而不重新启动)。
  • @theswine,系统调用为您提供当前线程的 ID,该映射可让您找到 任何 线程的 ID,给定其 thread::id。这样更灵活。这不是严格意义上的泄漏,因为内存仍然可以访问,但是为了保持内存使用有界(并应对线程 ID 被重用),您可以使用 thread_local 对象,该对象在其构造函数中添加到映射并从在其析构函数中映射。答案是展示解决方案的草图,如果您想要更健壮的东西,那就让它更健壮。
  • @JonathanWakely 你是对的,我没有意识到你可能想要获取线程 outside 的线程 ID。谢谢你的解释。
  • 我只是想强调while(tid ==0) 非常重要,因为父线程可能会在映射发生之前到达get thread id 语句。
【解决方案2】:

一些 pthread implementations,例如Android 21+,提供

pid_t pthread_gettid_np(pthread_t);

该实现可以使用struct pthread_t 的内部结构来检索本机线程ID,与在该线程上下文中调用时由gettid()syscall(SYS_gettid) 返回的ID 相同。

【讨论】:

    【解决方案3】:

    这个怎么样:

    pid_t gettid (void)
    {
        return syscall(__NR_gettid);
    }
    

    http://yusufonlinux.blogspot.com/2010/11/get-thread-id-from-linux.html

    看起来 __NR_gettid 是在 unistd.h 中定义的

    【讨论】:

    • 我认为如果您在std:threadpthreads 周围有一个包装器,这很有用,但我不能从线程外部调用它。 (如我错了请纠正我)。谢谢。
    猜你喜欢
    • 2019-03-19
    • 1970-01-01
    • 2014-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 2012-04-24
    相关资源
    最近更新 更多