问题 为什么glibc和pthread库都定义了相同的API?


为什么glibc和pthread库都定义了相同的API?这是快照

ubuntu@ubuntu:/lib$ objdump -T /lib/i386-linux-gnu/libc.so.6 |grep pthread_cond_signal
000f8360 g    DF .text  00000039  GLIBC_2.3.2 pthread_cond_signal
0012b940 g    DF .text  00000039 (GLIBC_2.0)  pthread_cond_signal

ubuntu@ubuntu:/lib$ objdump -T /lib/i386-linux-gnu/libpthread.so.0 |grep pthread_cond_signal
0000b350 g    DF .text  0000007c (GLIBC_2.0)  pthread_cond_signal
0000af90 g    DF .text  000000fc  GLIBC_2.3.2 pthread_cond_signal

5830
2018-06-22 17:43


起源



答案:


libpthread.so 也是glibc的一部分,它们都包含 (相同) 一些符号的定义。

如果你寻找 pthread_create 相反,你会看到它只出现在 libpthread.so  - 这意味着程序必须链接到 libpthread.so 实际创建线程,但可以在仅链接到的单线程程序中使用互斥锁和条件变量 libc.so。这对于存在于共享内存中并用于与单独进程同步的进程间互斥和进程间条件变量很有用。 (感谢Zan Lynx在下面的评论)。

链接到两者都不是问题 libpthread.so 和 libc.so 即使他们都定义了符号。 ELF链接器允许多个共享库包含相同符号的定义,链接器将选择它看到的第一个,并将其用于对该符号的所有引用,这称为 符号插入。允许定义多个符号的另一个特性是,如果一个库包含 弱符号 这将由具有相同名称的非弱符号覆盖。在这种情况下的定义 这两个库是相同的,所以使用哪个库并不重要  libpthread.so 覆盖那些 libc.so。如果你使用 LD_DEBUG  并更改链接器的参数顺序 你应该能够看到符号实际找到的库。

除了定义相同符号的两个库之外,每个库还有两个符号定义,具有不同的定义 符号版本GLIBC_2.0 和 GLIBC_2.3.2。此符号版本控制允许多个定义共存于同一个库中,以便将新的,改进的函数版本添加到库中,而不会破坏与旧实现链接的代码。这允许相同的共享库适用于使用LinuxThreads的应用程序和使用NPTL的应用程序。链接到库时引用将绑定的默认符号是 pthread_cond_signal@GLIBC_2.3.2 对应于 NPTL 实现该功能(NPTL首先包含在glibc 2.3.2中)。旧的符号, pthread_cond_signal@GLIBC_2.0,是旧的LinuxThreads实现,它是NPTL提供之前的默认实现。与旧版(2.3.2之前版本)glibc链接的应用程序将受到约束 pthread_cond_signal@GLIBC_2.0 并将使用该符号。


11
2018-06-26 15:13



你没错,pthread_create没有在libc.so.6中定义。但是为什么我们在链接时不会得到pthread_cond_signal的多个定义错误? - Lunar Mushrooms
回答更新来描述 符号插入 - Jonathan Wakely
我不相信这个答案是完全正确的。 glibc中的定义只是占位符,并且对于pthread操作只有空的do-nothing定义。 libpthread.so中的定义会覆盖这些定义。这适用于希望在多线程程序中单线程但线程安全的库。 - Zan Lynx
@ZanLynx啊,我觉得你是对的 - 我的坏 - 我想 pthread_mutex_lock 可以使用类似的函数而无需链接到libpthread,但它们似乎确实是无操作。 - Jonathan Wakely


答案:


libpthread.so 也是glibc的一部分,它们都包含 (相同) 一些符号的定义。

如果你寻找 pthread_create 相反,你会看到它只出现在 libpthread.so  - 这意味着程序必须链接到 libpthread.so 实际创建线程,但可以在仅链接到的单线程程序中使用互斥锁和条件变量 libc.so。这对于存在于共享内存中并用于与单独进程同步的进程间互斥和进程间条件变量很有用。 (感谢Zan Lynx在下面的评论)。

链接到两者都不是问题 libpthread.so 和 libc.so 即使他们都定义了符号。 ELF链接器允许多个共享库包含相同符号的定义,链接器将选择它看到的第一个,并将其用于对该符号的所有引用,这称为 符号插入。允许定义多个符号的另一个特性是,如果一个库包含 弱符号 这将由具有相同名称的非弱符号覆盖。在这种情况下的定义 这两个库是相同的,所以使用哪个库并不重要  libpthread.so 覆盖那些 libc.so。如果你使用 LD_DEBUG  并更改链接器的参数顺序 你应该能够看到符号实际找到的库。

除了定义相同符号的两个库之外,每个库还有两个符号定义,具有不同的定义 符号版本GLIBC_2.0 和 GLIBC_2.3.2。此符号版本控制允许多个定义共存于同一个库中,以便将新的,改进的函数版本添加到库中,而不会破坏与旧实现链接的代码。这允许相同的共享库适用于使用LinuxThreads的应用程序和使用NPTL的应用程序。链接到库时引用将绑定的默认符号是 pthread_cond_signal@GLIBC_2.3.2 对应于 NPTL 实现该功能(NPTL首先包含在glibc 2.3.2中)。旧的符号, pthread_cond_signal@GLIBC_2.0,是旧的LinuxThreads实现,它是NPTL提供之前的默认实现。与旧版(2.3.2之前版本)glibc链接的应用程序将受到约束 pthread_cond_signal@GLIBC_2.0 并将使用该符号。


11
2018-06-26 15:13



你没错,pthread_create没有在libc.so.6中定义。但是为什么我们在链接时不会得到pthread_cond_signal的多个定义错误? - Lunar Mushrooms
回答更新来描述 符号插入 - Jonathan Wakely
我不相信这个答案是完全正确的。 glibc中的定义只是占位符,并且对于pthread操作只有空的do-nothing定义。 libpthread.so中的定义会覆盖这些定义。这适用于希望在多线程程序中单线程但线程安全的库。 - Zan Lynx
@ZanLynx啊,我觉得你是对的 - 我的坏 - 我想 pthread_mutex_lock 可以使用类似的函数而无需链接到libpthread,但它们似乎确实是无操作。 - Jonathan Wakely