【发布时间】:2021-06-09 06:10:06
【问题描述】:
我目前正在开发一个旨在在 Linux for MIPSEL 平台上运行的应用程序。
该应用程序在其 DSO 之一内使用 POSIX 信号量,在我的例子中,注意的是在应用程序所依赖的一个 DSO 内使用的 sem_init() 函数。
该应用程序当前使用的是 GLIBC_2.31,但我在使用 GLIBC_2_26 时也观察到了同样的现象。
现在我将解释异常和故障排除的当前状态。
当我注意到当信号量增加其值时等待信号量的进程不会唤醒时,这一切都发生了。
为了记录,我知道对于多处理,信号量必须位于使用信号量的进程之间共享的内存区域中。
现在,使用 strace 进一步调查,我还注意到我使用 sem_init(&semaphore, 1, 0) 初始化的信号量导致了 private,尽管我将它初始化为共享。
futex(0x774ce0bc, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1, {tv_sec=1615204364, tv_nsec=515578961}, FUTEX_BITSET_MATCH_ANY) = -1 ETIMEDOUT (Connection timed out)
我在这个问题上执行的下一步是使用 gdb 调试信号量初始化过程。在那里我发现在这个特殊的组合中,MIPSEL - LINUX - GLIBC,sem_init() 存在两个版本:
$ mipsel-linux-objdump -T libpthread.so.0 | grep sem_init
00012e30 g DF .text 00000040 (GLIBC_2.0) sem_init
00012dd0 g DF .text 00000060 GLIBC_2.2 sem_init
由于某种原因,链接器决定将我的代码链接到 older(不支持共享信号量)而不是 newer。
查看 GLIBC 代码,特别是在实现 sem_init() 的地方 (/nptl/sem_init.c),我意识到 sem_init() 是一个别名,两个符号明确地标识了函数的实现。
我的下一步是直接调用我需要的函数__new_sem_init(),以确保任何我不知道的链接器炼金术会干扰我的意图。
很遗憾,符号没有导出,无法使用。
查看我的库liba.so,它使用了sem_wait()、sem_init() 和sem_post(),我注意到这些符号都是由libpthread.so.0 导出的。
$ mipsel-linux-nm -D libpthread.so.0 | grep sem_
00014a10 T sem_clockwait
00013784 T sem_close
00012e70 T sem_destroy
00012e70 T sem_destroy
00013b14 T sem_getvalue
00013b00 T sem_getvalue
00012e30 T sem_init
00012dd0 T sem_init
000131b8 T sem_open
00014ab0 T sem_post
00014b90 T sem_post
00014508 T sem_timedwait
00013f40 T sem_trywait
00013fac T sem_trywait
00013920 T sem_unlink
00013eb0 T sem_wait
00014020 T sem_wait
但是查看liba.so 依赖项,我很惊讶该库仅依赖于主libc 库(libc.so.6)并且不依赖于libpthread.so.0,其中实际的@987654336实现了@符号。
$ /lib/ld-2.31.so --list /usr/lib/liba.so
linux-vdso.so.1 (0x7ffaa000)
libc.so.6 => /lib/libc.so.6 (0x77ddc000)
/lib/ld-2.31.so (0x77f8a000)
我想这可能与我的问题密切相关,但我不知道如何将这两个事实联系起来。
如何使用其依赖项不提供的符号编译和链接liba.so?
$ mipsel-linux-objdump -T libc.so.6 | grep sem
000fab80 g DF .text 00000070 GLIBC_2.0 semget
000fabf0 g DF .text 000000b0 GLIBC_2.2 semctl
000faca0 w DF .text 00000074 GLIBC_2.3.3 semtimedop
000359d0 g DF .text 00000074 GLIBC_2.0 sigisemptyset
00149854 g DF .text 000000b0 (GLIBC_2.0) semctl
000fab60 g DF .text 00000018 GLIBC_2.0 semop
$
如何强制 GNU 链接器链接到 sem_init@@GLIBC_2.2 而不是 sem_init@GLIBC_2.0?
【问题讨论】:
标签: linux mips semaphore ld glibc