我正在使用prctl()
来更改C语言中的pthreads线程名称:
// Set our thread name to assist with debugging a running process
char *threadName = calloc(16, sizeof(char));
sprintf(threadName, "My Own Thread");
prctl(PR_SET_NAME, threadName);
我的问题是在char *threadName
通话之后是否应该立即释放prctl()
?
prcrl()
是否可以安全地复制字符串参数,是否可以在需要时释放所提供的变量?
当我免费使用valgrind进行内存测试时,没有发现任何问题。我担心会导致难以跟踪的并发/内存问题。
编辑:我不认为建议的问题Can calloc ever safely be used without free?回答了有关系统/内核功能的具体问题,特别是prctl()
要求调用者不要释放提供的内存
答案 0 :(得分:2)
是的,通常,标准函数会在返回之前根据需要复制缓冲区,而将原始传递的缓冲区的所有权留给调用函数。
答案 1 :(得分:1)
我找不到任何文件明确表明释放传递给prctl( PR_SET_NAME, name )
的字符串是安全的(很可能存在于某处)。
对手册页,glibc源代码和Linux内核源代码的检查表明,调用prctl()
之后释放内存是安全的。
Linux prctl()
man page为PR_SET_NAME
指出了这一点:
PR_SET_NAME(自Linux 2.6.9起)
使用中的值设置调用线程的名称
(char *) arg2
指向的位置。名称最多 16个字节长,包括终止的空字节。 (如果 字符串的长度,包括终止的空字节, 超过16个字节,该字符串将被静默截断。)这是 可以通过pthread_setname_np(3)
设置的相同属性 并使用pthread_getname_np(3)
进行检索。该属性是 同样可以通过/proc/self/task/[tid]/comm
访问,其中tid
是调用线程的名称。
这里的关键是语句“同样可以通过/proc/self/task/[tid]/comm
访问该属性”。这意味着必须将提供的字符串复制到内核空间中。措辞“在由( char * ) arg2
指向的位置使用值”确实看起来令人困惑和不清楚,这有可能直接使用传递给prctl()
的字符串。但是“要通过/proc/...
进行访问,需要在内核空间中进行复制。
glibc source有点难以理解。在您的进程调用prctl()
时,我无法确切地找到实际执行的代码,但是我发现的是直接将指针传递给内核的系统调用。
Linux kernel source is pretty clear。将字符串从用户空间复制到内核空间:
case PR_SET_NAME:
comm[sizeof(me->comm) - 1] = 0;
if (strncpy_from_user(comm, (char __user *)arg2,
sizeof(me->comm) - 1) < 0)
return -EFAULT;
set_task_comm(me, comm);
proc_comm_connector(me);
break;
确定的测试将是调用prctl()
设置名称,然后修改传递给prctl()
的字符串。如果线程名称未更改,则必须已创建副本。