有关共享库的问题

Rah*_*obi 2 linux shared-libraries

我对共享库有一些疑问

  1. 运行二进制文件时,谁将加载共享库取决于共享库(.so)?

  2. 共享库在哪里加载?

  3. 如果共享库已经加载并且我运行二进制文件取决于加载的库,在这种情况下共享库将要加载,或者二进制文件将使用加载的库?

osg*_*sgx 5

运行二进制文件时,谁将加载共享库取决于共享库(.so)?

当您exec使用二进制文件时,Linux内核将读取文件的elf标头。所有动态链接的ELF文件/lib/ld-linux.so.2(运行时动态链接器)已.interp在ELF文件的程序头(解释器)中注册。存在解释器时,Linux内核将加载解释器的ELF(通过根据其标头将其映射到内存中),并跳入其入口点。

运行时动态链接器将读取您的动态链接程序,找到所有需要的共享库并将它们加载到内存中(再次使用mmapELF标头中的和信息)。

共享库在哪里加载?

在运行时库搜索路径($LD_LIBRARY_PATH/etc/ld.so.conf)中列出的所有目录中搜索共享库。

用于加载每个库的内存地址由确定ld-linux.so.2(并且可能由内核确定,例如,将起始地址随机化)。

库加载的实际代码在glibc中,elf/rtld.c文件为http://fxr.watson.org/fxr/source/elf/rtld.c?v=GLIBC27#L1731

 1731   /* Load all the libraries specified by DT_NEEDED entries. ....  */
 1735   _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
Run Code Online (Sandbox Code Playgroud)

然后,链接器将在对象文件之间连接符号引用(重定位过程,如果懒惰绑定处于活动状态,则有时在实际引用符号时完成)。

如果共享库已经加载并且我运行二进制文件取决于加载的库,在这种情况下共享库将要加载,或者二进制文件将使用加载的库?

您应该知道如何mmap使用文件。硬盘(HDD或SSD)上存储了文件,应将其加载到内存中才能执行。链接器不会mmap整个库文件;仅包含库数据和代码的部分。另外,mmap系统调用是惰性的,它不会将所有请求的文件片段都加载到内存中,而只是记住相应的虚拟页面和文件偏移量。首次访问虚拟页面时,pagefault将发生(主要页面故障),并且将从HDD中读取文件的一部分(Linux可能会从磁盘加载更多页面;还有一些预取程序,它们会在引导过程的早期将库读取到内存中)。

如果多个进程mmap使用同一个文件,则将使用写时复制机制。这意味着:如果仅读取内存页面,则将有一个物理页面。几个虚拟页面将被映射到它;所有这些都带有不允许的“写”访问权限。对于页面上的每个写访问,将执行复制(通过次要pagefault),如果将原始物理页面复制到新的物理页面中,则将完成复制;并且将为进行写访问的进程更改映射。从pagefault中断返回后,将重新启动写指令,将操作写入到自己的页面副本中。

共享库的大多数可执行代码未写入,因此在所有进程之间共享。数据段(.data,.bss,.tdata,.bss)将不会共享,因为有写入操作。重定位也会取消共享某些页面。