-pthread、-lpthread 和最小的动态链接时间依赖性
-pthread, -lpthread and minimal dynamic linktime dependencies
这个 answer 建议 -pthread
优于 -lpthread
因为预定义宏。
根据经验,-pthread
只给我一个额外的宏:#define _REENTRANT 1
而且它似乎也强制 libpthread.so.0
作为动态链接时间依赖项。
当我使用 -lpthread
编译时,仅当我实际调用任何 pthread
函数时才会添加该依赖项。
这对我来说更好,因为这样我就不必在我的构建脚本中以不同方式对待多线程程序。
所以我的问题是,-pthread
与 -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
而不是 -lpthread
的想法可能已经过时了大约十年半(相对于 glibc,也就是说)。在现代 glibc 中,切换到线程完全是动态的,这取决于是否链接了 pthreads 库。 glibc headers 中的任何内容都不会根据是否定义 _REENTRANT
来更改其行为。
作为动态切换的示例,请考虑 FILE *
个流。流上的某些操作是锁定的,例如 putc
。无论您是否正在编译 single-threaded 程序,它都会调用相同的 putc
函数;它不是 re-routed 预处理器对 "pthread-aware" putc
。发生的情况是 do-nothing 存根函数用于执行锁定和解锁动作。当链接线程库时,这些函数会被实际函数覆盖。
我只是粗略地 grep
浏览了 glibc 安装的包含文件树。在 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 仓库的主分支中找不到它。
而且,哦,看,就在几天前(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.
看到了吗?:)
另一个答案解释说 -pthread
(在编译和 link 时)在功能上等同于 -lpthread
(仅在 link 时)当 C 库是 GNU C 库时。但这不是世界上唯一的 C 库。
我不知道 当前 代的 POSIX 兼容操作系统是否需要 link -lpthread
以上的任何东西线程应用程序的时间,但如果您在编译和 link 时都使用 -pthread
,您至少会让那些试图保持旧铁 运行.[=17= 的人的生活更轻松]
话虽如此,如果您不在不使用的程序上使用-pthread
(或-lpthread
),老铁也会更快乐需要使用线程。 "Generic project builds" 不是个好主意。
共享库在不需要时被拉入的问题最好由 -Wl,--as-needed
(与 GNU 兼容的 link 用户)解决。这只是为了向后兼容而默认不启用。
这个 answer 建议 -pthread
优于 -lpthread
因为预定义宏。
根据经验,-pthread
只给我一个额外的宏:#define _REENTRANT 1
而且它似乎也强制 libpthread.so.0
作为动态链接时间依赖项。
当我使用 -lpthread
编译时,仅当我实际调用任何 pthread
函数时才会添加该依赖项。
这对我来说更好,因为这样我就不必在我的构建脚本中以不同方式对待多线程程序。
所以我的问题是,-pthread
与 -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
而不是 -lpthread
的想法可能已经过时了大约十年半(相对于 glibc,也就是说)。在现代 glibc 中,切换到线程完全是动态的,这取决于是否链接了 pthreads 库。 glibc headers 中的任何内容都不会根据是否定义 _REENTRANT
来更改其行为。
作为动态切换的示例,请考虑 FILE *
个流。流上的某些操作是锁定的,例如 putc
。无论您是否正在编译 single-threaded 程序,它都会调用相同的 putc
函数;它不是 re-routed 预处理器对 "pthread-aware" putc
。发生的情况是 do-nothing 存根函数用于执行锁定和解锁动作。当链接线程库时,这些函数会被实际函数覆盖。
我只是粗略地 grep
浏览了 glibc 安装的包含文件树。在 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 仓库的主分支中找不到它。
而且,哦,看,就在几天前(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.
看到了吗?:)
另一个答案解释说 -pthread
(在编译和 link 时)在功能上等同于 -lpthread
(仅在 link 时)当 C 库是 GNU C 库时。但这不是世界上唯一的 C 库。
我不知道 当前 代的 POSIX 兼容操作系统是否需要 link -lpthread
以上的任何东西线程应用程序的时间,但如果您在编译和 link 时都使用 -pthread
,您至少会让那些试图保持旧铁 运行.[=17= 的人的生活更轻松]
话虽如此,如果您不在不使用的程序上使用-pthread
(或-lpthread
),老铁也会更快乐需要使用线程。 "Generic project builds" 不是个好主意。
共享库在不需要时被拉入的问题最好由 -Wl,--as-needed
(与 GNU 兼容的 link 用户)解决。这只是为了向后兼容而默认不启用。