Linux 平台 C/C++ 代码中设置线程名
生活随笔
收集整理的這篇文章主要介紹了
Linux 平台 C/C++ 代码中设置线程名
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一般來說,Linux 平臺的 C/C++ 程序可以用 prctl() 或 pthreads 的 pthread_setname_np() 接口為一個線程設置線程名。prctl() 可以用于為當前線程設置線程名,pthread_setname_np() 則可以用于為當前進程的任意線程設置線程名。
prctl() 的函數聲明如下:
#include <sys/prctl.h>int prctl(int option, unsigned long arg2, unsigned long arg3,unsigned long arg4, unsigned long arg5);pthread_setname_np() 的函數聲明如下:
#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);如果想要通過 prctl() 為其它線程設置線程名,一般需要先將線程名放在某個地方,然后在目標線程中拿到線程名并設下去。最常見的還是,在線程啟動之前準備好線程名,新線程啟動之后,立即設置線程名。比如,像下面這樣:
#include <stdio.h> #include <stdlib.h> #include <sys/prctl.h> #include <pthread.h>char *thread_name1 = nullptr; char *thread_name2 = nullptr;void* thread1(void* arg) {prctl(PR_SET_NAME, thread_name1);while (1) {printf("thread1\n");sleep(1000);} }void* thread2(void* arg) {while (1) {printf("thread2\n");sleep(1000);} }int main() {pthread_t th1, th2;void* retval = NULL;thread_name1 = "THREAD1";pthread_create(&th1, NULL, thread1, NULL);pthread_create(&th2, NULL, thread2, NULL);printf("main thread\n");pthread_join(th1, &retval);pthread_join(th2, &retval); }曾經項目中遇到過一個設置線程名不生效的問題,最終同事查出來是因為設置的線程名太長導致的。
glibc 的 pthread_setname_np() 函數實現 (glibc 版本 2.34,代碼位于 glibc-2.34/nptl/pthread_setname.c) 如下:
/* pthread_setname_np -- Set thread name. Linux versionCopyright (C) 2010-2021 Free Software Foundation, Inc.This file is part of the GNU C Library.The GNU C Library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General Public License aspublished by the Free Software Foundation; either version 2.1 of theLicense, or (at your option) any later version.The GNU C Library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with the GNU C Library; see the file COPYING.LIB. Ifnot, see <https://www.gnu.org/licenses/>. */#include <errno.h> #include <fcntl.h> #include <pthreadP.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/prctl.h>#include <not-cancel.h>int __pthread_setname_np (pthread_t th, const char *name) {const struct pthread *pd = (const struct pthread *) th;/* Unfortunately the kernel headers do not export the TASK_COMM_LENmacro. So we have to define it here. */ #define TASK_COMM_LEN 16size_t name_len = strlen (name);if (name_len >= TASK_COMM_LEN)return ERANGE;if (pd == THREAD_SELF)return __prctl (PR_SET_NAME, name) ? errno : 0;#define FMT "/proc/self/task/%u/comm"char fname[sizeof (FMT) + 8];sprintf (fname, FMT, (unsigned int) pd->tid);int fd = __open64_nocancel (fname, O_RDWR);if (fd == -1)return errno;int res = 0;ssize_t n = TEMP_FAILURE_RETRY (__write_nocancel (fd, name, name_len));if (n < 0)res = errno;else if (n != name_len)res = EIO;__close_nocancel_nostatus (fd);return res; } versioned_symbol (libc, __pthread_setname_np, pthread_setname_np,GLIBC_2_34);#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_12, GLIBC_2_34) compat_symbol (libpthread,__pthread_setname_np, pthread_setname_np,GLIBC_2_12); #endif可以看到,當設置的線程名長度超過 16 個字符時,直接返回失敗。當通過 pthread_setname_np() 為當前線程設置線程名時,通過調用 prctl() 實現,當給其它線程設置線程名時,則通過向 procfs 文件系統中,線程的 comm 文件中寫入線程名來實現。
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的Linux 平台 C/C++ 代码中设置线程名的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebRTC 的 AudioSource
- 下一篇: WebRTC 视频发送和接收处理过程