设置线程名的两种方式:prctl和pthread_setname_np

19 篇文章 2 订阅

前言:


对于长期在linux 中开发的同学,这两个函数应该是非常熟悉的。prctl 的功能十分强大,但对于设置线程名称单独的特性而言,pthread_setname_np 更是灵活些。

1. prctl


       #include <sys/prctl.h>

       int prctl(int option, unsigned long arg2, unsigned long arg3,
                 unsigned long arg4, unsigned long arg5);

prctl 的option 太多了,功能十分强大,这里只针对线程名。

       PR_SET_NAME (since Linux 2.6.9)
              Set the name of the calling thread, using the value in the location pointed to by (char *) arg2.  The name can be up to 16 bytes long, including the ter‐
              minating null byte.  (If the length of the string, including the terminating null byte, exceeds 16 bytes, the string is silently truncated.)  This is the
              same attribute that can be set  via  pthread_setname_np(3)  and  retrieved  using  pthread_getname_np(3).   The  attribute  is  likewise  accessible  via
              /proc/self/task/[tid]/comm, where tid is the name of the calling thread.

       PR_GET_NAME (since Linux 2.6.11)
              Return  the name of the calling thread, in the buffer pointed to by (char *) arg2.  The buffer should allow space for up to 16 bytes; the returned string
              will be null-terminated.

大致意思:

  • PR_SET_NAME

从linux 2.6.9 引入,用以设置当前线程的名称,参数arg2 代表线程名称,不过这个名称最多支持16个字节,包括\0。如果arg2 的名称超过了16个字节,将会被截成16个字节。

线程名可以通过节点/proc/[pid]/task/[tid]/comm查看。

  • PR_GET_NAME

从linux 2.6.11 引入,返回当前线程的名称,使用参数进行返回。要求参数arg2 的空间要大于16个字节。

2. pthread_setname_np


这个函数比较相比较与prctl 就纯粹了,只是用于设置线程的名称。但是,不同的是接口是设置指定线程的线程名。

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <pthread.h>
int pthread_setname_np(pthread_t thread, const char *name);
int pthread_getname_np(pthread_t thread,
                      char *name, size_t len);

第一个参数:需要设置/获取 名称的线程;

第二个参数:要设置/获取 名称的buffer;

同样的,要求name 的buffer 空间不能超过16个字节,不然会报错 ERANGE

详细的可以看下描述:

By  default,  all the threads created using pthread_create() inherit the program name.  The pthread_setname_np() function can be used to set a unique name for a
thread, which can be useful for debugging multithreaded applications.  The thread name is a meaningful C language string, whose length is restricted to 16 char‐
acters, including the terminating null byte ('\0').  The thread argument specifies the thread whose name is to be changed; name specifies the new name.

The  pthread_getname_np() function can be used to retrieve the name of the thread.  The thread argument specifies the thread whose name is to be retrieved.  The
buffer name is used to return the thread name; len specifies the number of bytes available in name.  The buffer specified by name should be at least 16  charac‐
ters in length.  The returned thread name in the output buffer will be null terminated.

大致意思:

通过pthread_setname_np 给一个线程设置唯一名称,这样对于多线程开发中很有意义。要求名称不超16字节,包括结尾的\0。

通过pthread_getname_np 能够获取一个线程的名称,参数的buffer 用以接受name,要求这个buffer 最少要有16个字节的空间。如果buffer 空间小于thread name,最终会返回null。

3. 注意


如果修改主线程的名称,其实也就修改了进程名。

4. 实例


#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(105);          // allow main program to set the thread name
   return NULL;
}

int
main(int argc, char *argv[])
{
   pthread_t thread;
   int rc;
   char thread_name[NAMELEN];
   
   rc = pthread_getname_np(pthread_self(), thread_name, NAMELEN);
   if (rc != 0)
       errExitEN(rc, "pthread_getname_np current");

   printf("current thread default name is: %s\n", thread_name);

   rc = pthread_setname_np(pthread_self(), (argc > 1) ? argv[1] : "MAIN_MM");
   if (rc != 0)
       errExitEN(rc, "pthread_setname_np");

   sleep(2);

   rc = pthread_create(&thread, NULL, threadfunc, NULL);
   if (rc != 0)
       errExitEN(rc, "pthread_create");

   rc = pthread_getname_np(thread, thread_name, NAMELEN);
   if (rc != 0)
       errExitEN(rc, "pthread_getname_np");

   printf("Created a thread. Default name is: %s\n", thread_name);
   rc = pthread_setname_np(thread, (argc > 1) ? argv[1] : "SUB_MM");
   if (rc != 0)
       errExitEN(rc, "pthread_setname_np");

   sleep(2);

   rc = pthread_getname_np(thread, thread_name, NAMELEN);
   if (rc != 0)
       errExitEN(rc, "pthread_getname_np");
   printf("The thread name after setting it is %s.\n", thread_name);

   rc = pthread_join(thread, NULL);
   if (rc != 0)
       errExitEN(rc, "pthread_join");

   printf("Done\n");
   exit(EXIT_SUCCESS);
}

运行结果:

current thread default name is: test
Created a thread. Default name is: MAIN_MM
The thread name after setting it is SUB_MM.

Done

通过命令行也可以确认是否修改:

ps H -C MAIN_MM -o 'pid tid cmd comm'
  PID   TID CMD                         COMMAND
10592 10592 ./test                      MAIN_MM
10592 10593 ./test                      SUB_MM

ps 结果看到主线程名修改后,进程名也是变的。

cat /proc/10592/status 
Name:	MAIN_MM
Umask:	0002

查看进程的Name 可以核对。

参考:

https://man7.org/linux/man-pages/man3/pthread_setname_np.3.html

https://man7.org/linux/man-pages/man2/prctl.2.html

  • 11
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

私房菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值