如何在Linux中更改单个线程的名称? [英] How do I change the name of one single thread in Linux?
问题描述
我发现了有关更改线程名称的this post。
我尝试了prctl()
和pthread_setname_np()
函数。两者都会更改所有我的线程的名称。换句话说,它似乎没有像预期的那样工作。
我使用:
pthread_setname_np(pthread_self(), "thread ONE");
和
pthread_setname_np(pthread_self(), "thread TWO");
根据先运行的线程,两个线程都会显示线程一或线程二。我原以为其中一个是线程一个,另一个是线程两。
我做错了什么吗?
正如tzig在一条评论中提出的,我测试了该示例,如pthreadsetname_np()文档中所示。但是,我需要使用至少两个线程进行测试,因此我按如下所示更改了代码,使其具有thread1和thread2。
默认情况下,我可以启动htop
并使用F4仅显示名称包括THREAD
的线程/进程(我也可以使用命令行使用不同的名称:./a.out MULTIFOO MULTIBAR
,然后使用单词MULTI
作为筛选器)。
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#define NAMELEN 16
#define errExitEN(en, msg)
do { errno = en; perror(msg);
exit(EXIT_FAILURE); } while (0)
static void *
threadfunc(void *parm)
{
sleep(15); // allow main program to set the thread name
return NULL;
}
int
main(int argc, char **argv)
{
pthread_t thread1, thread2;
int rc;
char thread_name[NAMELEN];
rc = pthread_create(&thread1, NULL, threadfunc, NULL);
if (rc != 0)
errExitEN(rc, "pthread_create");
rc = pthread_create(&thread2, NULL, threadfunc, NULL);
if (rc != 0)
errExitEN(rc, "pthread_create");
// test name of thread1
//
rc = pthread_getname_np(thread1, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("Created thread1. Default name is: %s
", thread_name);
rc = pthread_setname_np(thread1, (argc > 1) ? argv[1] : "THREADFOO");
if (rc != 0)
errExitEN(rc, "pthread_setname_np");
sleep(2);
rc = pthread_getname_np(thread1, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("The thread1 name after setting it is %s.
", thread_name);
// test name of thread2
//
rc = pthread_getname_np(thread2, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("Created thread2. Default name is: %s
", thread_name);
rc = pthread_setname_np(thread2, (argc > 2) ? argv[2] : "THREADBAR");
if (rc != 0)
errExitEN(rc, "pthread_setname_np");
sleep(2);
rc = pthread_getname_np(thread2, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("The thread2 name after setting it is %s.
", thread_name);
// thread1 name changed too?
//
rc = pthread_getname_np(thread1, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("The thread1 name after setting thread2 name is %s.
", thread_name);
rc = pthread_join(thread1, NULL);
if (rc != 0)
errExitEN(rc, "pthread_join");
rc = pthread_join(thread2, NULL);
if (rc != 0)
errExitEN(rc, "pthread_join");
printf("Done
");
exit(EXIT_SUCCESS);
}
附注:原版中有一个错误:在我的示例中,我使用第二个参数作为第二个线程的名称,并始终使用请注意,rc = pthread_getname_np(thread, thread_name, (argc > 2) ? atoi(argv[1]) : NAMELEN);
atoi()
使用argv[1]
而不是argv[2]
。(我已将该错误报告给手册页维护人员。)
NAMELEN
作为缓冲区的长度。我没有理由减少这个金额。
结果:
不出所料,pthread_getname_np()
起作用了。太棒了!
htop
或cat /proc/self/task/<tid>/comm
都返回设置的姓氏。我猜这是Linux内核中的一个错误...然而,我的进程还有由nvidia驱动程序创建的其他线程,这些线程具有不同的名称。以防万一,我尝试了Linux - how to change info of forked processes in C中的函数,因为它显示了&fork()‘ed";,因此看起来确实是错误的。但由于每个任务在/proc
下都有自己的条目...但我认为问题在于,这些线程与它们的主进程共享相同的内存,并且argv[0]
数据只有一个位置。换句话说,他们实现了在内部工作pthread_setname_np()
,但不会在ps
和htop
等工具中反映该名称。
推荐答案
好的,我知道如何让它工作了。您希望将名称直接写入proc
文件。比它预期的效果要好。每个线程都有自己的名称。
首先,我们需要知道线程标识符(它是编号,而不是pthline_id)。在Linux下,您可以使用以下函数获取该信息:
pid_t gettid()
{
return static_cast<pid_t>(syscall(SYS_gettid));
}
现在要设置线程名称,请在写入模式下打开comm文件并将名称写入其中:
void set_thread_name(std::string const & name)
{
if(name.length() > 15)
throw std::range_error("thread name is limited to 15 chars");
pid_t const tid(gettid());
std::ofstream comm("/proc/" + std::to_string(tid) + "/comm");
comm << name;
}
我使用C++,这简化了事情。当然,您可以在C:中执行相同的操作
void set_thread_name(const char * name)
{
pid_t tid;
char filename[6 + 5 + 5 + 1];
if(strlen(name) > 15)
{
errno = EINVAL;
return -1;
}
tid = gettid();
snprintf(filename, sizeof(filename), "/proc/%d/comm", tid);
FILE * comm(fopen(filename, "w"));
fprintf(comm, "%s", name);
fclose(comm);
}
现在我的每个线程都有一个不同的名称。感谢Nate给了我这个想法(尽管他的评论并不完全是这样读的)。
您可能还希望使用pthread_setname_np()
。该函数不会以某种方式更新您直接写入comm
文件名称。
这篇关于如何在Linux中更改单个线程的名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!