如何在Linux中更改单个线程的名称? [英] How do I change the name of one single thread in Linux?

查看:19
本文介绍了如何在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()起作用了。太棒了!

但是,htopcat /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(),但不会在pshtop等工具中反映该名称。

推荐答案

好的,我知道如何让它工作了。您希望将名称直接写入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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆