"pthread_setname_np"在此范围内未声明。

3

我在我的应用程序中创建了多个线程。我想为每个pthread分配一个名称,所以我使用了pthread_setname_np,这在Ubuntu上有效,但在SUSE Linux上无效。

我通过谷歌了解到'_np'表示 '非可移植',而此API在Linux的所有OS版本中都不可用。

因此,现在我只想在API可用时才执行它。如何确定API是否可用?我需要像这样的东西。

#ifdef SOME_MACRO
    pthread_setname_np(tid, "someName");
#endif
3个回答

4
您可以使用特性测试宏_GNU_SOURCE来检查此函数是否可用:
#ifdef _GNU_SOURCE
    pthread_setname_np(tid, "someName");
#endif

但是,手册指出,pthread_setname_nppthread_getname_np 是在 glibc 2.12 中引入的。因此,如果您使用的是较早的glibc(比如2.5),则定义 _GNU_SOURCE 将无济于事。

因此,最好避免使用这些不可移植的函数,您可以在创建线程时自己为其命名,例如使用线程ID和数组之间的映射:

pthread_t tid[128];
char thr_names[128][256]; //each name corresponds to on thread in 'tid'

您可以使用以下命令检查 glibc 版本:
getconf GNU_LIBC_VERSION

我正在使用glibc 2.11.1,所以这个宏对我不起作用。无论如何,谢谢。 - Srikanth
1
“_GNU_SOURCE” 不是一个你应该“读取”以测试 GNU 特定 API 是否存在的宏,而是一个你应该“设置”以使用 GNU 特定 API 的宏,对吗? - Craig McQueen
@CraigMcQueen 你说得完全正确。我可能是指,定义它以获取GNU特定的API,然后建议使用它们。你对变体的担忧...我没有其他办法,只能检查实现特定的宏。我个人会按照我建议的方法去做(自己命名),而不是用ifdef语句来混乱代码(但我必须承认,在我编写的几个pthread应用程序中,我从未遇到过需要给它们命名的情况)。 - P.P

3
自从glibc 2.12引入了这个函数,你可以使用以下代码:
#if ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
    pthread_setname_np(tid, "someName");
#endif

你的回答很有帮助,但部分是错误的。预处理器表达式应该是:#if (2 < __GLIBC__) || ((2 == __GLIBC__) && (12 <= __GLIBC_MINOR__)) - Preston L. Bannister

1
这种事情——查找编译环境中是否存在特定函数——是人们使用GNU Autoconf脚本的原因。
如果您的项目已经在使用autoconf,您可以在检查了pthreads编译器和链接器标志后将其添加到您的配置源代码中。
AC_CHECK_FUNCS(pthread_setname_np)

...并且如果该函数存在,它将定义一个名为HAVE_PTHREAD_SETNAME_NP的宏。


问题在于,不同的平台对于相同的函数名pthread_setname_np()具有不同的参数。因此仅仅测试函数是否存在是不够的。请参考Can I set the name of a thread in pthreads/Linux? - Craig McQueen
是的,您可以使用AC_COMPILE_IFELSE()来测试您拥有哪个变量的pthread_setname_np() - caf
我刚刚尝试了上面的AC_CHECK_FUNCS(),但在glibc-2.19(Ubuntu 14.04)系统上似乎不起作用,尽管我可以正常编译使用该函数的代码:checking for pthread_setname_np... no也许需要一些额外的魔法来定义_GNU_SOURCE? - fencekicker
@fencekicker:是的,如果你想在一个autoconf项目中使用"_GNU_SOURCE",你应该在编译器被调用之前,在configure中早期使用"AC_GNU_SOURCE"宏。这样你就不需要手动定义它了。 - caf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接