【问题标题】:How to set the name of a thread in Linux pthreads?如何在 Linux pthreads 中设置线程的名称?
【发布时间】:2011-01-23 02:34:32
【问题描述】:

有没有办法在Linux中设置线程的名称?

我的主要目的是它在调试时会有所帮助,如果该名称通过例如暴露出来也很好。 /proc/$PID/task/$TID/...

【问题讨论】:

  • 您能否通过一些示例说明名称在调试中的用途?
  • @skwllsp:所以你可以更容易地识别线程?
  • 当您的程序具有大量不同的线程时,线程名称肯定会有所帮助,每个线程都执行特定的操作(例如管道设置,其中每个线程对每个数据包执行部分处理任务)。我已经看到了这样做的必要性。具有操作系统意识的良好调试工具也应该能够显示这些名称,但不清楚目前有多少调试器这样做。
  • Possibly a better solution 作为默认函数不反映线程的/proc/self/comm 文件中的名称。或者它复制了姓氏集,这与没有它一样没用。对于所有工具(例如htopps),允许直接写入 comm 文件并按预期工作。

标签: c linux pthreads


【解决方案1】:

从 glibc v2.12 开始,您可以使用 pthread_setname_nppthread_getname_np 设置/获取线程名称。

这些接口在其他一些 POSIX 系统(BSD、QNX、Mac)上以各种略有不同的形式提供。

设置名称将是这样的:

#include <pthread.h>  // or maybe <pthread_np.h> for some OSes

// Linux
int pthread_setname_np(pthread_t thread, const char *name);

// NetBSD: name + arg work like printf(name, arg)
int pthread_setname_np(pthread_t thread, const char *name, void *arg);

// FreeBSD & OpenBSD: function name is slightly different, and has no return value
void pthread_set_name_np(pthread_t tid, const char *name);

// Mac OS X: must be set from within the thread (can't specify thread ID)
int pthread_setname_np(const char*);

你可以找回名字:

#include <pthread.h>  // or <pthread_np.h> ?

// Linux, NetBSD:
int pthread_getname_np(pthread_t th, char *buf, size_t len);
// some implementations don't have a safe buffer (see MKS/IBM below)
int pthread_getname_np(pthread_t thread, const char **name);
int pthread_getname_np(pthread_t thread, char *name);

// FreeBSD & OpenBSD: dont' seem to have getname/get_name equivalent?
// but I'd imagine there's some other mechanism to read it directly for say gdb

// Mac OS X:
int pthread_getname_np(pthread_t, char*, size_t);

正如您所见,它在 POSIX 系统之间并非完全可移植,但据我所知,它在 linux 中应该是一致的。除了 Mac OS X(您只能在线程内执行此操作)之外,其他的至少很容易适应跨平台代码。

来源:

【讨论】:

  • 如果无法检索名称,我不明白 pthread_set_name_np() 在 BSD 上的意义...?
  • @kralyk,是的,它对于应用内使用不是那么有用,但我怀疑它可以通过其他机制检索(例如,直接通过 gdb 或其他方式从内存中读取?)... FWIW NetBSD与 Linux 接口兼容(并使用类似 printf 的用法稍微扩展它们)
  • @drfrogsplat - 定义名称最大长度的常量在哪里?我没有看到任何关于它的文档
  • @kralyk 我认为在使用 gdb 或top -H进行调试时会很有用
【解决方案2】:

prctl(2) 函数与PR_SET_NAME 选项一起使用(请参阅the docs)。

请注意,旧版本的文档有点混乱。他们说

为调用进程设置进程名

但由于线程是 Linux 上的轻量级进程 (LWP),因此在这种情况下,一个线程就是一个进程。

您可以通过ps -o cmd 或以下方式查看线程名称:

cat /proc/$PID/task/$TID/comm

或在()cat /proc/$PID/task/$TID/stat 之间:

4223 (kjournald) S 1 1 1 0...

或来自 GDB info threads 双引号之间:

* 1    Thread 0x7ffff7fc7700 (LWP 6575) "kjournald" 0x00007ffff78bc30d in nanosleep () at ../sysdeps/unix/syscall-template.S:84                                                                                  

【讨论】:

  • 请注意,实际的线程名称将在 /proc/$PID/tasks/$TID/stat 中
  • @nos 尽管它们在/proc 的目录列表中不可见,但可以通过/proc/$TID 访问线程(因为基本上与进程相同)。
  • @nos,至少在内核版本 3.2.0 中,它是 /proc/$PID/task/$TID/stat(任务上没有)
  • 为了完整起见,我将把它留在这里,更改主线程名称可能会造成陷阱:lists.linuxfoundation.org/pipermail/bugme-new/2008-October/…
  • @AndrewWagner 即使线程未列在/proc/ 的目录列表中,如果您访问/proc/$TID/,您仍然可以获得线程的信息。
【解决方案3】:

您可以通过创建字典映射pthread_tstd::string 自己实现这一点,然后将pthread_self() 的结果与您要分配给当前线程的名称相关联。请注意,如果您这样做,您将需要使用互斥锁或其他同步原语来防止多个线程同时修改字典(除非您的字典实现已经为您执行此操作)。您还可以使用线程特定的变量(参见pthread_key_createpthread_setspecificpthread_getspecificpthread_key_delete)来保存当前线程的名称;但是,如果这样做,您将无法访问其他线程的名称(而使用字典,您可以从任何线程遍历所有线程 id/name 对)。

【讨论】:

  • 请注意,此解决方案可在 Linux、Mac OS X 和所有符合单一 UNIX 规范的系统上移植。 (Aaron Digulla 提出的使用“prctl”的建议不可移植)。
  • 这似乎是一个非常糟糕的主意,人们不应该这样做。
  • 又怎么能从APP外面看到呢?像在ps,还是top?
  • 这条评论有点过时了。 dfrogsplat 的答案是最好的,因为它现在支持跨平台。
  • +1 - 在带有过时或外来 C 库的嵌入式 Linux 中仍然有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-04
  • 2012-07-27
  • 2010-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多