Linux 如何打印 pthread_t

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1759794/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:54:32  来源:igfitidea点击:

How to print pthread_t

c++clinuxpthreads

提问by dimba

Searched, but don't come across a satisfying answer.

搜索,但没有遇到令人满意的答案。

I know there's no a portable way to print a pthread_t.

我知道没有一种可移植的方式来打印 pthread_t。

How do you do it in your app?

你如何在你的应用程序中做到这一点?

Update:

更新:

Actually I don't need pthread_t, but some small numeric id, identifying in debug message different threads.

实际上我不需要 pthread_t,而是一些小的数字 id,在调试消息中识别不同的线程。

On my system (64 bit RHEL 5.3) it's defined as unsigned long int, so it's big number and just printing it eats a valuable place in debug line. How does gdb assignshort tids?

在我的系统(64 位 RHEL 5.3)上,它被定义为 unsigned long int,所以它是一个很大的数字,只是打印它在调试行中占据了宝贵的位置。gdb如何分配短 tids?

采纳答案by sth

This will print out a hexadecimal representation of a pthread_t, no matter what that actually is:

这将打印出 a 的十六进制表示pthread_t,无论它实际上是什么:

void fprintPt(FILE *f, pthread_t pt) {
  unsigned char *ptc = (unsigned char*)(void*)(&pt);
  fprintf(f, "0x");
  for (size_t i=0; i<sizeof(pt); i++) {
    fprintf(f, "%02x", (unsigned)(ptc[i]));
  }
}

To just print a small id for a each pthread_tsomething like this could be used (this time using iostreams):

只需为每个打印一个小的 idpthread_t可以使用这样的东西(这次使用 iostreams):

void printPt(std::ostream &strm, pthread_t pt) {
  static int nextindex = 0;
  static std::map<pthread_t, int> ids;
  if (ids.find(pt) == ids.end()) {
    ids[pt] = nextindex++;
  }
  strm << ids[pt];
}

Depending on the platform and the actual representation of pthread_tit might here be necessary to define an operator<for pthread_t, because std::mapneeds an ordering on the elements:

根据平台和它的实际表示,pthread_t这里可能需要定义一个operator<for pthread_t,因为std::map需要对元素进行排序:

bool operator<(const pthread_t &left, const pthread_t &right) {
  ...
}

回答by James McNellis

In this case, it depends on the operating system, since the POSIX standard no longer requires pthread_tto be an arithmetic type:

在这种情况下,它取决于操作系统,因为POSIX 标准不再需要pthread_t是算术类型

IEEE Std 1003.1-2001/Cor 2-2004, item XBD/TC2/D6/26 is applied, adding pthread_tto the list of types that are not required to be arithmetic types, thus allowing pthread_tto be defined as a structure.

应用 IEEE Std 1003.1-2001/Cor 2-2004,项目 XBD/TC2/D6/26,添加pthread_t到不需要是算术类型的类型列表中,从而允许pthread_t定义为结构。

You will need to look in your sys/types.hheader and see how pthread_tis implemented; then you can print it how you see fit. Since there isn't a portable way to do this and you don't say what operating system you are using, there's not a whole lot more to say.

你需要查看你的sys/types.h标题,看看pthread_t是如何实现的;然后你可以打印出你认为合适的方式。由于没有可移植的方法来执行此操作,并且您没有说明您使用的是什么操作系统,因此没有更多要说的。

Edit:to answer your new question, GDB assigns its own thread ids each time a new thread starts:

编辑:为了回答您的新问题,每次新线程启动时GDB 都会分配自己的线程 ID

For debugging purposes, gdb associates its own thread number—always a single integer—with each thread in your program.

出于调试目的,gdb 将它自己的线程号(始终是一个整数)与程序中的每个线程相关联。

If you are looking at printing a unique number inside of each thread, your cleanest option would probably be to tell each thread what number to use when you start it.

如果您正在考虑在每个线程内打印一个唯一的编号,那么您最干净的选择可能是在您启动它时告诉每个线程使用什么编号。

回答by Bill Lynch

On Centos 5.4 x86_64, pthread_t is a typedef to a unsigned long.

在 Centos 5.4 x86_64 上,pthread_t 是 unsigned long 的 typedef。

Therefore, we could do this...

因此,我们可以这样做...

#include <iostream>
#include <pthread.h>

int main() {
    pthread_t x;
    printf("%li\n", (unsigned long int) x);
    std::cout << (unsigned long int) x << "\n";
}

回答by Roman Nikitchenko

OK, seems this is my final answer. We have 2 actual problems:

好的,这似乎是我的最终答案。我们有两个实际问题:

  • How to get shorter unique IDs for thread for logging.
  • Anyway we need to print real pthread_t ID for thread (just to link to POSIX values at least).
  • 如何为用于日志记录的线程获取更短的唯一 ID。
  • 无论如何,我们需要为线程打印真实的 pthread_t ID(至少只是为了链接到 POSIX 值)。

1. Print POSIX ID (pthread_t)

1.打印POSIX ID (pthread_t)

You can simply treat pthread_t as array of bytes with hex digits printed for each byte. So you aren't limited by some fixed size type. The only issue is byte order. You probably like if order of your printed bytes is the same as for simple "int" printed. Here is example for little-endian and only order should be reverted (under define?) for big-endian:

您可以简单地将 pthread_t 视为字节数组,每个字节都打印有十六进制数字。因此,您不受某些固定大小类型的限制。唯一的问题是字节顺序。您可能喜欢打印字节的顺序与简单“int”打印的顺序相同。这是小端的示例,对于大端,只有顺序应该恢复(在定义下?):

#include <pthread.h>
#include <stdio.h>

void print_thread_id(pthread_t id)
{
    size_t i;
    for (i = sizeof(i); i; --i)
        printf("%02x", *(((unsigned char*) &id) + i - 1));
}

int main()
{
    pthread_t id = pthread_self();

    printf("%08x\n", id);
    print_thread_id(id);

    return 0;
}

2. Get shorter printable thread ID

2. 获取更短的可打印线程 ID

In any of proposed cases you should translate real thread ID (posix) to index of some table. But there is 2 significantly different approaches:

在任何建议的情况下,您都应该将真实线程 ID (posix) 转换为某个表的索引。但是有两种截然不同的方法:

2.1. Track threads.

2.1. 跟踪线程。

You may track threads ID of all the existing threads in table (their pthread_create() calls should be wrapped) and have "overloaded" id function that get you just table index, not real thread ID. This scheme is also very useful for any internal thread-related debug an resources tracking. Obvious advantage is side effect of thread-level trace / debug facility with future extension possible. Disadvantage is requirement to track any thread creation / destruction.

您可以跟踪表中所有现有线程的线程 ID(它们的 pthread_create() 调用应该被包装)并具有“重载”id 函数,该函数只为您提供表索引,而不是真正的线程 ID。该方案对于任何与内部线程相关的调试资源跟踪也非常有用。明显的优势是线程级跟踪/调试工具的副作用,未来可能扩展。缺点是需要跟踪任何线程的创建/销毁。

Here is partial pseudocode example:

这是部分伪代码示例:

pthread_create_wrapper(...)
{
   id = pthread_create(...)
   add_thread(id);
}

pthread_destruction_wrapper()
{
   /* Main problem is it should be called.
      pthread_cleanup_*() calls are possible solution. */
   remove_thread(pthread_self());
}

unsigned thread_id(pthread_t known_pthread_id)
{
  return seatch_thread_index(known_pthread_id);
}

/* user code */
printf("04x", thread_id(pthread_self()));

2.2. Just register new thread ID.

2.2. 只需注册新的线程 ID。

During logging call pthread_self() and search internal table if it know thread. If thread with such ID was created its index is used (or re-used from previously thread, actually it doesn't matter as there are no 2 same IDs for the same moment). If thread ID is not known yet, new entry is created so new index is generated / used.

在记录期间调用 pthread_self() 并搜索内部表,如果它知道线程。如果创建了具有此类 ID 的线程,则使用其索引(或从以前的线程中重新使用,实际上无关紧要,因为同一时刻没有 2 个相同的 ID)。如果尚不知道线程 ID,则会创建新条目,以便生成/使用新索引。

Advantage is simplicity. Disadvantage is no tracking of thread creation / destruction. So to track this some external mechanics is required.

优点是简单。缺点是没有跟踪线程创建/销毁。因此,为了跟踪这一点,需要一些外部机制。

回答by Employed Russian

GDB uses the thread-id (aka kernel pid, aka LWP) for short numbers on Linux. Try:

GDB 使用线程 ID(又名内核 pid,又名 LWP)作为 Linux 上的短数字。尝试:

  #include <syscall.h>
  ...

    printf("tid = %d\n", syscall(SYS_gettid));

回答by David R Tribble

You could try converting it to an unsigned short and then print just the last four hex digits. The resulting value might be unique enough for your needs.

您可以尝试将其转换为无符号短整型,然后仅打印最后四位十六进制数字。结果值可能足够独特以满足您的需求。

回答by LnxPrgr3

You could do something like this:

你可以这样做:

int thread_counter = 0;
pthread_mutex_t thread_counter_lock = PTHREAD_MUTEX_INITIALIZER;

int new_thread_id() {
    int rv;
    pthread_mutex_lock(&thread_counter_lock);
    rv = ++thread_counter;
    pthread_mutex_unlock(&thread_counter_lock);
    return rv;
}

static void *threadproc(void *data) {
    int thread_id = new_thread_id();
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

If you can rely on having GCC (clang also works in this case), you can also do this:

如果您可以依靠 GCC(在这种情况下,clang 也可以使用),您也可以这样做:

int thread_counter = 0;

static void *threadproc(void *data) {
    int thread_id = __sync_add_and_fetch(&thread_counter, 1);
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

If your platform supports this, a similar option:

如果你的平台支持这个,一个类似的选项:

int thread_counter = 0;
int __thread thread_id = 0;

static void *threadproc(void *data) {
    thread_id = __sync_add_and_fetch(&thread_counter, 1);
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

This has the advantage that you don't have to pass around thread_id in function calls, but it doesn't work e.g. on Mac OS.

这样做的好处是您不必在函数调用中传递 thread_id,但它不适用于例如 Mac OS。

回答by sgowd

if pthread_t is just a number; this would be the easiest.

如果 pthread_t 只是一个数字;这将是最简单的。

int get_tid(pthread_t tid)
{
    assert_fatal(sizeof(int) >= sizeof(pthread_t));

    int * threadid = (int *) (void *) &tid;
    return *threadid;
}

回答by Jim

A lookup table (pthread_t : int)could become a memory leak in programs that start a lot of short-lived threads.

(pthread_t : int)在启动大量短期线程的程序中,查找表可能会导致内存泄漏。

Creating a hash of the bytes of the pthread_t(whether it be structure or pointer or long integer or whatever) may be a usable solution that doesn't require lookup tables. As with any hash there is a risk of collisions, but you could tune the length of the hash to suit your requirements.

创建字节的散列pthread_t(无论是结构、指针还是长整数或其他)可能是一个不需要查找表的可用解决方案。与任何散列一样,存在冲突的风险,但您可以调整散列的长度以满足您的要求。

回答by user2173833

I know, this thread is very old. Having read all above posts, I would like to add one more idea to handle this in a neat way: If you get into the mapping business anyway (mapping pthread_to to an int), you could as well go one step further in readability. Make your pthread_create_wrapper such that it takes a string, too...the name of the thread. I learned to appreciate this "SetThreadName()" feature on windows and windows CE. Advantages: Your ids are not just numbers but you also see, which of your threads has which purpose.

我知道,这个线程很老了。阅读完以上所有帖子后,我想再添加一个想法来以简洁的方式处理这个问题:如果您无论如何都进入映射业务(将 pthread_to 映射到 int),那么您还可以在可读性方面更进一步。使你的 pthread_create_wrapper 也接受一个字符串......线程的名称。我学会了欣赏 Windows 和 Windows CE 上的“SetThreadName()”功能。优点:您的 id 不仅是数字,而且您还可以看到,您的哪个线程有什么用途。