如何更改 Linux 中单个线程的名称?

2024-03-12

我发现了这个帖子 https://stackoverflow.com/questions/2369738/how-to-set-the-name-of-a-thread-in-linux-pthreads关于更改线程的名称。

我尝试过prctl() and pthread_setname_np()功能。两者都更改了名称ALL我的线程。换句话说,它似乎没有按预期工作。

I used:

pthread_setname_np(pthread_self(), "thread ONE");

and

pthread_setname_np(pthread_self(), "thread TWO");

根据哪个线程先运行,两个线程都会显示“线程一”或“线程二”。我期望其中一个是“线程一”,另一个是“线程二”。

难道我做错了什么?


正如 Tzig 在评论中提出的那样,我测试了 pthread_setname_np() 文档中所示的示例。但是,我需要使用至少两个线程进行测试,因此我将代码更改为具有线程 1 和线程 2。

默认情况下,我可以启动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\n", 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.\n", 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\n", 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.\n", 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.\n", 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\n");
   exit(EXIT_SUCCESS);
}
P.S. There is a bug in the original:
rc = pthread_getname_np(thread, thread_name,
                               (argc > 2) ? atoi(argv[1]) : NAMELEN);

请注意,atoi() uses argv[1]代替argv[2]。 (我已向手册页维护者报告了该错误。)

在我的示例中,我使用第二个参数作为第二个线程的名称,并始终使用NAMELEN作为我的缓冲区的长度。我没有理由减少这个数额。

RESULTS:

正如预期的那样,pthread_getname_np()作品。伟大的!

但是,那htop or cat /proc/self/task/<tid>/comm全部返回设置的姓氏。我猜这是 Linux 内核中的一个错误...但是,我的进程还有由 NVidia 驱动程序创建的其他线程,并且这些线程具有不同的名称。


以防万一,我尝试了中找到的功能Linux - 如何更改 C 中分叉进程的信息 https://stackoverflow.com/questions/5881556/linux-how-to-change-info-of-forked-processes-in-c这似乎是错误的,因为它说“fork()'ed”。但由于每个任务都有自己的条目/proc...但我认为问题是线程与其主进程共享相同的内存,并且只有一个位置用于argv[0]数据。换句话说,他们实施了一个pthread_setname_np()哪个有效内部,但不会在工具中反映该名称,例如ps and htop.


好的,我找到了如何让它发挥作用。你想把名字写在proc直接归档。比它按预期工作。每个线程都有自己的名称。

首先,我们需要知道线程标识符(它是数字,而不是 pthread_id)。在Linux下,您可以使用以下函数获取该信息:

pid_t gettid()
{
    return static_cast<pid_t>(syscall(SYS_gettid));
}

现在要设置线程名称,以写入模式打开通讯文件并在其中写入名称:

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 file.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何更改 Linux 中单个线程的名称? 的相关文章

  • 消息循环如何使用线程?

    我有点困惑 想知道我是否被误导了 在另一篇文章中 我被告知 只有当你显式创建新线程时才会创建它们 C 程序默认是单线程的 当我打开未在 ollydbg 中显式创建新线程的程序时 我多次注意到通常有 2 个线程在运行 我想了解消息循环如何在不
  • 如何从纯文本中查找键值存储中的值

    给定一个纯文本文件 其中包含 FOO foo BAR bar BAZ baz 我们如何grep使用键获取值 Use a 向后看 https regex101 com r q3FNpe 1 grep Po lt FOO w file foo
  • 并行处理的ThreadPool和Pool

    有没有办法在 python 中同时使用 ThreadPool 和 Pool 来通过指定您希望使用的 CPU 和内核的数量来并行循环 例如 我将循环执行为 from multiprocessing dummy import Pool as T
  • 如何杀死正在运行的线程? [复制]

    这个问题在这里已经有答案了 可能的重复 杀死 pthread 中的线程 https stackoverflow com questions 2084830 kill thread in pthread 在包含线程启动的源代码之后 过了一会儿
  • 基于程序描述的多线程推荐

    我想描述我的程序的一些细节 并获得有关最适用的最佳多线程模型的反馈 我现在花了很多时间阅读有关 ThreadPool Threads Producer Consumer 等的内容 但尚未得出可靠的结论 我有一个文件列表 格式相同 但内容不同
  • 请求失败的错误:GLXBadDrawable (C++ bgfx)

    我试图用 glfw 和 bgfx 创建一个紫色窗口作为我的游戏引擎的起点 但是在启动二进制文件时它会抛出一个错误 我正在尝试创建紫色窗口 如下图所示 我正在使用 cmake 错误是 anuj fedora D C C c o build g
  • 为什么我的 sed 命令在使用变量时失败?

    使用 bash 我尝试插入日期变量并搜索该日期的日志文件 然后将输出发送到文件 如果我像这样对日期进行硬编码 它会起作用 sed n Nov 22 2010 p file gt log file 但如果我这样做就会失败 date Nov 2
  • 使用 C# 读取数百万个小文件

    我有数百万个每天生成的日志文件 我需要读取所有这些文件并将其放在一起作为单个文件 以便在其他应用程序中对其进行一些处理 我正在寻找最快的方法来做到这一点 目前我正在使用线程 任务和并行 如下所示 Parallel For 0 files L
  • Eclipse CDT 内置包含目录

    Under Eclipse CDT gt Project Settings gt C C General gt Paths and Symbols gt Includes gt GNU C 有一个包含路径的列表 有些是粗体的并且是特定于项目
  • 调试严重的 SIGILL 崩溃:文本段损坏

    我们的系统是基于 PowerPC 的运行 Linux 的嵌入式系统 我们遇到了随机的 SIGILL 崩溃 这种情况在各种应用程序中都会出现 崩溃的根本原因是将要执行的指令归零 这表明内存中的文本段已损坏 由于文本段是以只读方式加载的 因此应
  • 如何同时(并行)调用远程计算机上的相同功能

    我正在编写一个脚本 该脚本具有多个需要时间在不同远程计算机上执行的函数 有什么方法可以以并行方式同时调用命令它们吗 举个例子将不胜感激 谢谢 Invoke Command已经对每台计算机并行执行调用 作为内置功能的一部分 https tec
  • 在 C++ 中使用哪些字符串类?

    我们有一个用 C MFC 编写的多线程桌面应用程序 目前开发人员使用 CString 或 std string 可能取决于他们的心情 所以我们想选择一个实现 可能不是这两个 MFC 的 CString 基于写时复制 COW 习惯用法 有些人
  • elf .rel.text 部分中 R_386_32/R_386_PC32 的含义

    为了理解重定位的概念 我编写了一个简单的 chk c 程序 如下所示 1 include
  • 如何在生产环境中运行 spring boot 可执行 jar?

    Spring Boot 的首选部署方法是通过内部包含 tomcat 的可执行 jar 文件 它是从一个简单的开始java jar myapp jar 现在 我想将该 jar 部署到 EC2 上的 Linux 服务器上 我是否遗漏了某些内容
  • 来自外部 .diff 文件的交互式补丁

    Linux 是否有命令或程序允许交互式地修补源代码 在屏幕上打印每个块并在将其应用到文件之前等待确认 就像是git add p 但是从另一个 diff 文件中进行更改 您始终可以在 shell ruby python 中编写脚本 逐行读取该
  • x86-64 Linux 中不再允许使用 32 位绝对地址?

    64 位 Linux 默认使用小内存模型 将所有代码和静态数据置于 2GB 地址限制以下 这确保您可以使用 32 位绝对地址 旧版本的 gcc 对静态数组使用 32 位绝对地址 以便节省相对地址计算的额外指令 然而 这不再有效 如果我尝试在
  • 安装pipenv导致pip3无法使用

    我安装了pipenv using pip3 install pipenv 这给了我错误ImportError cannot import name main 为了解决这个错误我遵循这些说明 https stackoverflow com q
  • 文件在 rpm 规范文件中列出两次

    我的规范文件的文件部分如下所示 files prefix htdocs config prefix htdocs share settings config inc php 现在 由于配置文件已经包含在 prefix htdocs 我收到警
  • 如何使用AWK从文件中连续输出行

    我有一个多行文件 我想连续输出文件的某些行 比如第一次 从第1行打印到第5行 下次 打印第2行到第6行 依此类推 我发现 AWK 是一个非常有用的函数 我尝试自己编写代码 但它什么也没输出 以下是我的代码 bin bash for n in
  • 如何重新安装最新的cmake版本?

    我想在Linux环境下安装cmake的最新版本 我安装了 cmake 3 5 版 但某些应用程序不支持 我尝试通过卸载当前版本来升级它 但是当我使用 sudo apt get install cmake 重新安装时 我重新安装了相同的版本

随机推荐