通过查看
/proc/PID/maps
文件,可以看到在每个so文件的前面,有一个没有个名字的匿名映射的文件区间,其大小一般为4KB大小。通过gdb调试,可以知道这个映射的映射在ld.so加载一个so文件的时候,会通过mmap分配一个用来管理这个对应的so文件的、唯一的代表一个ld.so文件管理这个so文件的结构(就好像操作系统管理的每个进程都一个task_struct结构)link_map结构。在ld.so加载一个so文件的时候,首先会为这个so文件分配一个link_map,这个结构当然也顺便分配了这些结构中一些可变的结构的内容,比如说这个动态库的文件名,这个是变长的,所以需要在运行时动态的分配而不能写入一个link_map结构中。
这个文件的调用关系为:
mmap.S ENTRY (__mmap)
dl-minimal.c __libc_memalign
dl-minimal.c malloc
dl-minimal.c calloc
dl-object.c new = (struct link_map *) calloc (sizeof (*new) + audit_space + sizeof (*newname) + libname_len, 1)
dl-load.c _dl_map_object_from_fd
rtld.c _dl_map_object
注意:这里调用的__libc_memalign执行的并不是通常的通用malloc模块定义的动态内存实现。
page = __mmap (0, nup, PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
if (page == MAP_FAILED)
这里无论大小都将会将这个内容通过mmap装载入内存。这一点和malloc的实现不同,因为malloc一般只有大于128KB的时候才使用mmap系统调用。
然后在执行了真正的将so文件映射入内存的时候执行的时候:
同样的执行链:
_dl_map_object_from_fd
/* Remember which part of the address space this object uses. */
l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
c->prot,
MAP_COPY|MAP_FILE,
fd, c->mapoff);
联系客服