`CDLL()`如何找到要加载的文件,只有文件基名?

时间:2018-06-11 14:06:54

标签: python linux ctypes libc dynamic-loading

On Lubuntu 18.04

$ python3
>>> from ctypes import *
>>> libc = CDLL("libc.so.6")
>>> libc.printf
<_FuncPtr object at 0x7f10caf0d9a8>

我没有为libc.so.6指定路径,那么CDLL()如何找到要加载的文件?

来自Why does loading the libc shared library have "'LibraryLoader' object is not callable" error?

1 个答案:

答案 0 :(得分:1)

这是因为CDLL(或LibraryLoader或来自[Python]: ctypes - A foreign function library for Python的任何其他内容 - 以及可以进一步扩展的内容)使用“本机库加载系统”来处理库(搜索和)加载(包括依赖项)。
Ux 系统上,这通常由动态链接器/加载器完成。

现在,我假设你想知道为什么,例如找到 “/ lib / x86_64-linux-gnu / libc.so.6” ,即使 “/ lib / x86_64-linux-gnu “ $ {LD_LIBRARY_PATH}

来自[man7]: LD.SO(8)

  

程序 ld.so 处理a.out二进制文件,这是一种很久以前使用的格式; ld-linux.so * /lib/ld-linux.so.1 for libc5, /lib/ld-linux.so.2 对于glibc2)处理ELF,每个人现在已经使用了多年。否则,两者都具有相同的行为,并使用与ldd(1)ldconfig(8) /etc/ld.so.conf 相同的支持文件和程序

来自[man7]: LD(1)

  

链接器使用以下搜索路径来查找所需的共享库:
  ...
  8.对于ELF系统上的本机链接器,如果文件 /etc/ld.so.conf 存在,则在该文件中找到目录列表。

我的 VM上的示例

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> uname -a
Linux cfati-ubtu16x64-0 4.13.0-43-generic #48~16.04.1-Ubuntu SMP Thu May 17 12:56:46 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> which ls
/bin/ls
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> file /bin/ls
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=d0bc0fb9b3f60f72bbad3c5a1d24c9e2a1fde775, stripped
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> ldd /bin/ls
        linux-vdso.so.1 =>  (0x00007ffc0e2e1000)
        libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f64b63d0000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f64b6006000)
        libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f64b5d96000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f64b5b92000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f64b65f2000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f64b5975000)
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> readelf -d /bin/ls

Dynamic section at offset 0x1de18 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 ...

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> ls -al /etc/ld.so.conf.d/*.conf
-rw-r--r-- 1 root root 32 iun  6 17:42 /etc/ld.so.conf.d/00vboxvideo.conf
-rw-rw-r-- 1 root root 38 nov 24  2014 /etc/ld.so.conf.d/fakeroot-x86_64-linux-gnu.conf
-rw-r--r-- 1 root root 44 ian 27  2016 /etc/ld.so.conf.d/libc.conf
-rw-r--r-- 1 root root 68 apr 15  2016 /etc/ld.so.conf.d/x86_64-linux-gnu.conf
lrwxrwxrwx 1 root root 43 mar  9 19:43 /etc/ld.so.conf.d/x86_64-linux-gnu_EGL.conf -> /etc/alternatives/x86_64-linux-gnu_egl_conf
lrwxrwxrwx 1 root root 42 mar  9 19:43 /etc/ld.so.conf.d/x86_64-linux-gnu_GL.conf -> /etc/alternatives/x86_64-linux-gnu_gl_conf
-rw-r--r-- 1 root root 56 ian 15 04:49 /etc/ld.so.conf.d/zz_i386-biarch-compat.conf
-rw-r--r-- 1 root root 58 ian 15 04:50 /etc/ld.so.conf.d/zz_x32-biarch-compat.conf
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> cat /etc/ld.so.conf.d/x86_64-linux-gnu.conf
# Multiarch support
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu

由于 libc 相关,还要检查[SO]: How does ctypes.cdll.LoadLibrary(None) work? (@CristiFati's answer)以便使用已加载的 libc 版本(并避免可能的冲突), if < / strong> libc 未静态链接。