免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: detian
打印 上一主题 下一主题

关于“linux共享库内部plt调用”澄清几个问题,继续讨论 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2009-01-04 16:48 |只看该作者
没有很多人有时间天天泡论坛的 学习2种方法 看书 google .

论坛徽章:
0
12 [报告]
发表于 2009-01-04 16:58 |只看该作者
原帖由 detian 于 2009-1-4 15:41 发表


对,我关心的就是同一个共享库中的两个函数之间的调用问题。
看我的代码。

mylib.c

#include
int a,aa;
int sum(int,int);
int _sum(int,int);

int sum(int x, int y)
{
  a = 1;
  aa =2 ...


明白LZ的意思了,LZ很善于思考啊!

论坛徽章:
0
13 [报告]
发表于 2009-01-04 17:03 |只看该作者

回复 #12 system888net 的帖子

关于LZ的同一个共享库中代码指令(sum ,_sum)在不同进程中不一样能否共享的问题:
linux 下的共享库so有两中方式供应用程序调用.
1. 不能内存中共享,这个时候的共享是对共享库的磁盘文件的共享,到内存中的时候就不是共享了,而是每个进程都会load一份,LZ 的例子就是这个情况.
2. 要做到内存中共享,也即物理上只有一份,LZ的共享库代码要生成与位置无关的就可以了(-fPIC).

[ 本帖最后由 system888net 于 2009-1-4 17:07 编辑 ]

论坛徽章:
0
14 [报告]
发表于 2009-01-04 17:18 |只看该作者
共享库的代码编译时如果不加-fPIC,那么生成的so在别的进程调用加载需要重定位, 重定位会修改代码段的内容,就成了每个使用这个.so的进程在内核里都会有一份so文件代码段的复制.每个复制都不一样,这时候取so文件代码段和数据段在内存中映射的位置都不一样.

论坛徽章:
0
15 [报告]
发表于 2009-01-05 23:29 |只看该作者

回复 #2 mik 的帖子

gdb也可以分析的

论坛徽章:
0
16 [报告]
发表于 2009-01-06 11:15 |只看该作者

回复 #14 system888net 的帖子

我加了-fPIC,生成的就是位置无关的代码,也就是说,里面的代码地址都是相对于加载地址(设为0,文件起始)的偏移,也就是说call 378 <_sum@plt>,这里的378就是相对于加载地址的偏移。那么,现这个库被两个进程分别加载到了0x00111000和0x00122000,那么,loader要不要对这个call重定位?如果要,则在进程1中就是call 0x00111378,在进程2中就是call 0x00122378。这么一来,这个call就是每进程一份,而不是共享的了。也就是说,所谓的共享库,在这里是不能共享的了。

如果我的看法是对的,那么凡是共享库中一个函数call另一个函数的地方,几乎都不能在内存中共享,而如果不共享,COW是以页为单位,通常的机器一页4K,这就是说,凡是有call的地方,它所在的页必须copy出来,因为每个进程都需要重定位。试想一下,4k能包含多么多的代码,而不掉用其他函数的函数又会有几个,这么说来,所谓的共享库,在内存中的代码,几乎是完全不能共享的。

不知道我的理解对不?

论坛徽章:
0
17 [报告]
发表于 2009-01-06 14:04 |只看该作者

回复 #16 detian 的帖子

我的理解好像不对,call 378 <_sum@plt>这条指令好像不需要重定位,好像说什么call指令的编码方式保存的是“目的地址相对于当前指令地址的偏移”,这个没明白,忘了原来书上怎么说得了,再看看教材。

论坛徽章:
0
18 [报告]
发表于 2009-01-06 17:47 |只看该作者
原帖由 detian 于 2009-1-6 11:15 发表
我加了-fPIC,生成的就是位置无关的代码,也就是说,里面的代码地址都是相对于加载地址(设为0,文件起始)的偏移,也就是说call 378 ,这里的378就是相对于加载地址的偏移。那么,现这个库被两个进程分别加载到 ...


先赞一下LZ的这种思考能力.


看如下(用gdb调试两个调用同一个so的程序):

第一个进程

  1. .....
  2. 0x002f6493 <sum+55>:    call   0x2f6348 <_sum@plt>    //地址随进程定位,  简称address1
  3. ......
  4. (gdb) x 0x2f6493
  5. 0x2f6493 <sum+55>:      0xfffeb0e8     //实际的指令代码,简称code1
  6. (gdb)
复制代码



第二个进程

  1. .....
  2. 0x00b60493 <sum+55>:    call   0xb60348 <_sum@plt>   //地址随进程定位, 简称address2
  3. ......
  4. (gdb) x 0xb60493
  5. 0xb60493 <sum+55>:      0xfffeb0e8    //实际的指令代码,简称code2
  6. (gdb)
复制代码


看到了address1<>address2
    但  code1=code2

所以所so库中的这条指令码在不同的进程中并没有被修改,实际上还是内存中共享的.

论坛徽章:
0
19 [报告]
发表于 2009-01-06 17:49 |只看该作者

回复 #18 system888net 的帖子

也就是在LZ的例子里sum和_sum在 -fPIC的选项编译下是共享的(也就是说LZ担心的指令码被修改并没有发生).

论坛徽章:
0
20 [报告]
发表于 2009-01-06 17:54 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP