这个答案建议-pthread
比使用-lpthread
预定义宏更好。
从经验上讲,-pthread
只给我一个额外的宏:#define _REENTRANT 1
而且它似乎也被强制libpthread.so.0
作为动态链接时依赖项。
当我使用编译时-lpthread
,仅当我实际调用任何pthread
函数时,才会添加该依赖项。
这对我来说最好,因为这样我就不必在构建脚本中对多线程程序进行不同的处理。
所以我的问题是,-pthread
vs -lpthread
还有什么,可以使用use -pthread
而不强制所说的动态链接时间依赖性?
示范:
$ echo 'int main(){ return 0; }' | c gcc -include pthread.h -x c - -lpthread && ldd a.out | grep pthread
$ echo 'int main(){ return pthread_self(); }' | c gcc -include pthread.h -x c - -lpthread && ldd a.out | grep pthread
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000003000c00000)
$ echo 'int main(){ return 0; }' | c gcc -include pthread.h -x c - -pthread && ldd a.out | grep pthread
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000003000c00000)
应该使用GCC的特殊选项-pthread
而不是GCC的想法-lpthread
可能已经过了十五年了(关于glibc)。在现代glibc中,基于pthreads库是否链接,切换到线程是完全动态的。glibc标头中的任何内容都_REENTRANT
不会根据是否定义而改变其行为。
作为动态切换的示例,请考虑FILE *
流。流上的某些操作已锁定,例如putc
。无论您是否在编译单线程程序,它都将调用同一putc
函数。预处理程序不会将它重新路由到“ pthread-aware” putc
。发生的事情是什么都不做的存根函数用于锁定和解锁的动作。当链接线程库时,这些函数将被覆盖为真实函数。
我只是粗略地grep
浏览了glibc安装的include文件树。在中features.h
,_REENTRANT
原因__USE_REENTRANT
被定义。反过来,似乎只有一件事取决于是否__USE_REENTRANT
存在,但是具有并行条件也可以使它成为可能。即,<unistd.h>
其中有:
#if defined __USE_REENTRANT || defined __USE_POSIX199506
/* Return at most NAME_LEN characters of the login name of the user in NAME.
If it cannot be determined or some other error occurred, return the error
code. Otherwise return 0.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1));
#endif
这看起来可疑且已过时;我在glibc git repo的master分支中找不到它。
而且,哦,瞧,就在几天前(12月6日),就此主题做出了承诺:
https://sourceware.org/git/?p=glibc.git;a=commit;h=c03073774f915fe7841c2b551fe304544143470f
Make _REENTRANT and _THREAD_SAFE aliases for _POSIX_C_SOURCE=199506L.
For many years, the only effect of these macros has been to make
unistd.h declare getlogin_r. _POSIX_C_SOURCE >= 199506L also causes
this function to be declared. However, people who don't carefully
read all the headers might be confused into thinking they need to
define _REENTRANT for any threaded code (as was indeed the case a long
time ago).
变化中:
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -849,7 +849,7 @@ extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) __THROW;
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern char *getlogin (void);
-#if defined __USE_REENTRANT || defined __USE_POSIX199506
+#ifdef __USE_POSIX199506
/* Return at most NAME_LEN characters of the login name of the user in NAME.
If it cannot be determined or some other error occurred, return the error
code. Otherwise return 0.
看到?:)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句