linux编程

时间秒杀一切 提交于 2021-02-16 03:46:29

为了能方便的区分一个进程中的每个线程,可以通过prctl()给每个线程取个名字。这样在会创建多个线程的程序执行过程中,就能知道一个pid或tid对应的是哪个线程,对调试程序有一定帮助。

prctl是个系统调用,可以用来读取和更改一个线程的属性。其用户态接口定义如下:

 
  1.  
    #include <sys/prctl.h>
  2.  
     
  3.  
    int prctl(int option, unsigned long arg2, unsigned long arg3,
  4.  
    unsigned long arg4, unsigned long arg5);

第一个参数option用来告诉prctl要对当前线程做什么操作,针对不同的操作,后面需要的参数个数也不同。其中用来获取和修改当前线程名字的option是下面两个:


PR_SET_NAME:设置当前线程的名字
PR_GET_NAME:获得当前线程的名字

这两个option都只需要一个参数,即用来存储线程名的字符串。

int prctl(int option, unsigned long arg2);

对于arg2有如下要求:
PR_SET_NAME:arg2存放将要设置的线程名的字符指针,即(char *)arg2。名字的长度最大为15字节,且应该以'\0'结尾。如果传入的字符串长度大于15字节,则字符串将被截断。
PR_GET_NAME:arg2需要是一个已经分配空间的字符指针,且长度不小于16。prctl成功返回后,arg2被赋值为当前线程名,以'\0'结尾。
例如设置线程名:

 
  1.  
    char tname[16];
  2.  
    memset(tname, 0, 16);
  3.  
    snprintf(tname, 16, "playctrl%u", playId);
  4.  
    prctl(PR_SET_NAME, tname);

获取线程名:

 
  1.  
    char tname[16];
  2.  
    prctl(PR_GET_NAME, tname);

prctl()执行成功返回0,失败返回-1,并设置errno。

注:prctl()只能设置/获取当前线程的名字,在glibc 2.12之后的版本中提供了两个扩展的接口pthread_setname_np()和pthread_getname_np(),可以在进程中设置和读取其他线程的名字。

线程名在内核中由struct task_struct结构的comm成员保存,prctl()系统调用操作线程名也是通过操作这个成员实现的。

 
  1.  
    #define TASK_COMM_LEN 16
  2.  
     
  3.  
    struct task_struct {
  4.  
    ...
  5.  
    char comm[TASK_COMM_LEN];
  6.  
    ...
  7.  
    };

从内核的task_struct结构定义以及prctl系统调用的实现也可以看出,线程名最多15个字符。

 

在/proc/PID/task/目录下,列出了进程中的所有活动的线程,每个线程默认的名字和进程名相同,都是cmdline,通过prctl设置线程名后便可很方便的找到线程名和tid的对应关系,如果存在/proc/PID/task/tid/comm文件,里面就存放着线程名。

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!