问题描述
这是我所知道的极限,请纠正这里的任何混淆。 In this question I ask why functionality provided by libm
isn't already exposed to the user with a Perl interface. 现在我想知道它是如何完成的。
CPAN 上有一个模块声称可以做到,名为 Math::Libm
。这工作正常,但作为一个关于实现的问题,当我使用它时,我发现 libm 不仅像在 Debian 上运行的任何 Perl 解释器一样映射到进程中,
7f719246d000-7f719247c000 r--p 00000000 fe:01 86513750 /usr/lib/x86_64-linux-gnu/libm-2.31.so
7f719247c000-7f7192516000 r-xp 0000f000 fe:01 86513750 /usr/lib/x86_64-linux-gnu/libm-2.31.so
7f7192516000-7f71925af000 r--p 000a9000 fe:01 86513750 /usr/lib/x86_64-linux-gnu/libm-2.31.so
7f71925af000-7f71925b0000 r--p 00141000 fe:01 86513750 /usr/lib/x86_64-linux-gnu/libm-2.31.so
7f71925b0000-7f71925b1000 rw-p 00142000 fe:01 86513750 /usr/lib/x86_64-linux-gnu/libm-2.31.so
但是 Math::libm
也映射到另一个 libm 共享对象中,
7fb649043000-7fb649044000 r--p 00000000 fe:01 11143927 /home/ecarroll/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/auto/Math/libm/libm.so
7fb649044000-7fb649049000 r-xp 00001000 fe:01 11143927 /home/ecarroll/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/auto/Math/libm/libm.so
7fb649049000-7fb64904a000 r--p 00006000 fe:01 11143927 /home/ecarroll/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/auto/Math/libm/libm.so
7fb64904a000-7fb64904b000 r--p 00006000 fe:01 11143927 /home/ecarroll/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/auto/Math/libm/libm.so
7fb64904b000-7fb64904c000 rw-p 00007000 fe:01 11143927 /home/ecarroll/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/auto/Math/libm/libm.so
这似乎是因为 Autoloader
加载了外部共享对象。
是否可以在不加载外部共享对象的情况下访问常驻进程中已有的符号?
解决方法
是否可以在不加载外部共享对象的情况下访问常驻进程中已有的符号?
您需要†加载 XS Libm.so
以从 Perl 访问 C 库函数,但是当 Libm.so
在运行时使用 dlopen()
加载时(请参阅 { {3}}) dl_load_file() 会识别出 Libm.so
需要 libm.so
但由于 libm.so
已经被 dynamic loader 加载(运行 perl 本身时),它不会被重新加载,但会返回现有的文件句柄,请参阅 dynamic linker 问答,因此共享库 libm.so
不会加载两次。
脚注:
† :但另请参阅 this 和 C::DynaLib 以了解不需要 XS 的替代方案