kernel 加载动态链接库问题

unbutun 2010-04-03 08:43:15
一个动态链接库,及从它在文件系统一个文件夹下开始到真正加载到内存中,其它进程可以访问,再到其卸载移出内存的过程是怎样的。


要求用实际代码说明


首先,一个xxx.so是在应用层被什么处理的,哪个程序?

其次,这个xxx.so进一步如何加载到内核的?

再次,在内核中哪一部分是处理动态链接库的代码?

最后,内核中对动态链接库的卸载代码在哪里?



谢谢了,各位xdjm, 谢谢了。
...全文
255 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
unbutun 2010-05-02
  • 打赏
  • 举报
回复
up



up
充电宝111 2010-04-06
  • 打赏
  • 举报
回复
实在没办法了再去加载动态库。
充电宝111 2010-04-06
  • 打赏
  • 举报
回复
1.对
2.加载动态库的实际代码是ld.so里面的,可执行程序里面会保存这个库的相关信息。
3.对,其实动态库就是推迟了link的过程,推迟到不能推迟为止,所以肯定是先加载ELF,实在没办法了再去加载。
unbutun 2010-04-06
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 cdbdyx 的回复:]
1.首先是编译阶段,这就涉及到ELF文件的相关知识,如果某个可执行程序依赖一个动态库里面的函数,那么编译生成的ELF会记录这个动态库的名字以及这个程序调用的符号,这就区别于静态链接。也就是这个可执行程序并不存xxx的实际代码。
int xxx(int x, int y)
{
printf("x is %d, y is %d\n");
}

把这个编成一个.so的话,然后

in……
[/Quote]


1.哥们,你说的意思是1,2是glibc中实现的,而加载elf分析是kernel做的对吗?

2.我的理解是加载动态库的代码实际上就在可执行的文件中,例如.init,加载完动态链接库,就到了你的1,2步,对吗?

3.elf分析应该是在2的所有过程之前做的,对吗?
充电宝111 2010-04-06
  • 打赏
  • 举报
回复
1.首先是编译阶段,这就涉及到ELF文件的相关知识,如果某个可执行程序依赖一个动态库里面的函数,那么编译生成的ELF会记录这个动态库的名字以及这个程序调用的符号,这就区别于静态链接。也就是这个可执行程序并不存xxx的实际代码。
int xxx(int x, int y)
{
printf("x is %d, y is %d\n");
}

把这个编成一个.so的话,然后

int main()
{
xxx(3,5);
}

2.执行这个程序,跟其他的ELF执行没什么两样,只是执行到这个函数的时候会有区别,这块有GOT和PLT等概念,对于普通函数的调用,编译器生成代码为call addr。其中addr是被调用函数的地址。调用来自动态链接库的函数时,其addr无法在link阶段确定,编译器只能生成call PLT[n]。PLT[n]指PLT表的第n个表项。
PLT每个表项有三行代码:
line1: jump GOT[n]
line2: push "func name"
line3: jump dl_runtime_resolve
因此当程序执行到call PLT[n]时,就跳到line1了,初始情况下,GOT[n]的值就是line2的地址。因此这条语句相当于nop。后两个语句就是调用dl_runtime_resolve去一个叫link map的结构中查找真正要调用的函数地址。这个过程完成后,GOT[n]的内容就被修改成真正要调用的函数的地址。这样下次程序再次走到call PLT[n]时,line1就直接跳到真正的来自动态链接库的函数地址,而不需要走line2和line3了。 (这也是为什么程序刚加载的时候执行比较慢,而后来执行就快起来的原因了。)

3.这些东西在glibc中实现,跟kernel有关的就是执行ELF文件的过程以及相关的syscall。
unbutun 2010-04-05
  • 打赏
  • 举报
回复
可否举个具体例子,就是比如:

int xxx(int x, int y)
{
printf("x is %d, y is %d\n");
}

把这个编成一个.so的话,然后

int main()
{
xxx(3,5);
}

被这个程序调,是哪部分先执行,内核中的代码还是应用层的什么(最好能给出具体代码位置)?

然后调用什么,最好是给出代码及整个代码(就是从建立整个.so开始从应用层到内核再到应用层的过程)走的过程。



谢谢了,大家都来帮帮忙了。
zigzag_xiang 2010-04-05
  • 打赏
  • 举报
回复
头次听说内核可以加载so库,本文孤陋寡闻!
linkejin 2010-04-05
  • 打赏
  • 举报
回复
我只知道程序在执行的时候,利用ld把so的代码段还有数据段,放到可执行程序对应的段里面,然后从入口函数开始执行。代码中有系统调用再到内核里面去。个人觉得so和内核没有关系,只跟程序的加载有关系。另外的话动态库的话有种惰性链接的说法,就是动态库的符号在真正执行的地方才会执行加载。具体可以参考link and loader,这一块确实比较复杂。
hallowwar 2010-04-05
  • 打赏
  • 举报
回复
应用层--》内核---》驱动层。
我就知道这个。高手来啊。
帅得不敢出门 2010-04-04
  • 打赏
  • 举报
回复
某个依赖a.so的程序b被启动
这时会执行ld.so的入口函数 由ld分析b的elf结构得到依赖的库然后加载a.so
再把控制权交到b的真正入口函数

unbutun 2010-04-04
  • 打赏
  • 举报
回复
可否举个具体例子,就是比如:

int xxx(int x, int y)
{
printf("x is %d, y is %d\n");
}

把这个编成一个.so的话,然后

int main()
{
xxx(3,5);
}

被这个程序调,是哪部分先执行,内核中的代码还是应用层的什么(最好能给出具体代码位置)?

然后调用什么,最好是给出代码及整个代码(就是从建立整个.so开始从应用层到内核再到应用层的过程)走的过程。



谢谢了,大家都来帮帮忙了。


unbutun 2010-04-04
  • 打赏
  • 举报
回复
主要是不熟悉,需要大家领领路
hallowwar 2010-04-04
  • 打赏
  • 举报
回复
关注,希望大侠能说的详细点,动态加载这东西确实难。
toborac 2010-04-03
  • 打赏
  • 举报
回复
1.用用程序自己包含库信息 链接时置入的
2.是ld,具体细节不了解
3.内核中和加载文件是一样的,都是分配虚拟地址空间,不同的是,多个应用程序公用的共享库只占用一份物理空间,而有各自的虚拟地址,不过这个虚拟地址经常是一样的
4.没人用了的时候这个动态库的内存会被释放掉,跟任何区域的释放没有区别

4,436

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧