你应该使用 GCC 的特殊选项的想法-pthread
代替-lpthread
可能已经过时了十五年(即相对于 glibc 而言)。在现代 glibc 中,到线程的切换完全是动态的,基于 pthreads 库是否链接。 glibc 标头中的任何内容都不会根据是否更改其行为_REENTRANT
被定义为。
作为动态切换的示例,请考虑FILE *
溪流。流上的某些操作是锁定的,例如putc
。无论您是否编译单线程程序,它都会调用相同的putc
功能;它不会被预处理器重新路由到“pthread-aware”putc
。所发生的情况是,不执行任何操作的存根函数用于完成锁定和解锁的动作。当链接线程库时,这些函数将被覆盖为真实函数。
我只是粗略地做了一个grep
通过 glibc 安装的包含文件树。在features.h
, _REENTRANT
causes __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.
See? :)