_dl_open() >> dl_open_worker() >> _dl_map_object() >> _dl_new_object()
2027 struct link_map *
2028 internal_function
2029 _dl_new_object (char *realname, const char *libname, int type,
2030 struct link_map *loader)
2031
2032 {
2033 struct link_map *l;
2034 int idx;
2035 size_t libname_len = strlen (libname) 1;
2036 struct link_map *new;
2037 struct libname_list *newname;
2038
2039 new = (struct link_map *) calloc (sizeof (*new) sizeof (*newname)
2040 libname_len, 1);
2041
………………..
2046
2047 new->l_name = realname;
2048 new->l_type = type;
2049 new->l_loader = loader;
2050
2051 new->l_scope = new->l_scope_mem;
2052 new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
2053
2054 if (GL(dl_loaded) != NULL)
2055 {
2056 l = GL(dl_loaded);
2057 while (l->l_next != NULL)
2058 l = l->l_next;
2059 new->l_prev = l;
2060 /* new->l_next = NULL; Would be necessary but we use calloc. */
2061 l->l_next = new;
2062
2063 /* Add the global scope. */
2064 new->l_scope[idx ] = &GL(dl_loaded)->l_searchlist;
2065 }
2066 else
2067 GL(dl_loaded) = new;
2068 GL(dl_nloaded);
………….
2080
2081 return new;
2082
2083 }
在2039行的内存分配是个把libname 和name的数据结构也一同分配,是一种零用整取的策略。从2043-2053行都是为struct link_map 的成员数据赋值。从2054-2067行则是把新的struct link_map* 加入到一个单链中,这是在以后是很有用的,因为这样在一个执行文档中假如要整体管理他相关的动态链接库,就能够以单链遍历。
假如要加载的动态链接库还没有被映射到进程的虚拟内存空间的话,那只是准备工作,真正的要点在 _dl_map_object_from_fd()这个函数开始的。因为这之后,每一步都有关动态链接库在进程中发挥他的作用而必须的条件。
这上段比较长,所以分段来看,
|
这里先开始就要从再找一遍,假如找到了已有的struct link_map* 要加载的libname(的而比较的依据是他的和st_ino,这是物理文档在内存中编号,且文档的设备号st_dev相同,这是从比较底层来比较文档,具体的原因,您能够参看我将要发表的《从linux的内存管理看文档共享的实现》)。之所以采取这样再查一遍,因为假如进程从要开始打开动态链接库文档,走到这里可能要经过很长的时间(据我作的实验来看,对第一次打开的文档大概也就在200毫秒左右---------主要的时间是硬盘的寻道和读盘,但这对于电脑的进程而言已是很长的时间了。)所以,有可能别的线程已读入了这个动态链接库,这样就没有必要再做下去了。这和内核在文档的打开文档所用的思想是一致的。
|
这一段所作的为下面的ELF文档的分节映射入内存做一点准备(要读写phdr的数组)。



