有关共享库的问题 [英] Questions about shared libraries

查看:53
本文介绍了有关共享库的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对共享库有疑问

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

  1. Who will load shared libraries when I run binary depends on shared libraries(.so)?

共享库在哪里加载?

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

If shared libraries were already loaded and I run binary depends on loaded libraries, in this case shared libraries will going to be loaded or binary will use loaded libraries?

推荐答案

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

Who will load shared libraries when I run binary depends on shared libraries(.so)?

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

When you execs the binary, the Linux kernel will read elf header of your file. All dynamically linked ELF files has /lib/ld-linux.so.2 (the runtime dynamic linker) registered in the program header .interp (interpreter) in ELF file. When interpreter is present, Linux kernel will load ELF of the interpreter (by mmaping it into memory according to its header), and jump into its Entry point.

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

The runtime dynamic linker will read your dynamically linked program, find all needed shared libraries and load them into memory (again using the mmap and information from ELF headers).

共享库在哪里加载?

Where shared libraries loaded?

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

Shared libraries are searched in all directories, listed in runtime library search path ($LD_LIBRARY_PATH and /etc/ld.so.conf).

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

The memory address which is used to load each library, is determined by ld-linux.so.2 (and possibly by kernel, for example to randomize the starting address).

库加载的实际代码在glibc的 elf/rtld.c 文件中

Actual code of library loading is in glibc, elf/rtld.c file 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);

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

Then linker will connect symbol references between object files (relocation process, it sometimes done when the symbol is actually referenced if lazy binding is active).

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

If shared libraries were already loaded and I run binary depends on loaded libraries, in this case shared libraries will going to be loaded or binary will use loaded libraries?

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

You should know how mmap works with files. There is file stored on Hard Drive (HDD or SSD), and it should be loaded into memory to be executed. Linker will not mmap entire library file; only sections with library data and code. Also, the mmap syscall is lazy, it doesn't load all requested pieces of file into memory, but just remember corresponding virtual pages and file offsets. On the first access to the virtual page, pagefault (major pagefault) will occur, and the part of file will be read from HDD (Linux may load more pages from disk; there are also prefetchers which read libraries to memory early in boot process).

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

If several processes mmaps the same file, the Copy-On-Write mechanism will be used. It means: if the memory page was only read, there will be one physical page. Several virtual pages will be mapped to it; all with disallowed "write" access. For every write access on the page, the Copy will be done (via minor pagefault), the original physical page if copied into new physical page; and the mapping will be changed for the process which did write access. After return from pagefault interrupt, the write instruction will be restarted, doing the write into own copy of the page.

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

Most executable code of shared libraries is not written to, so it is shared between all processes. The data segments (.data, .bss, .tdata, .bss) will be not shared, because there are writes to them. Relocations will also unshare some pages.

这篇关于有关共享库的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆