免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 24291 | 回复: 62

[讨论一下!]我发现动态库并不是只存在一份内存拷贝 [复制链接]

论坛徽章:
0
发表于 2008-09-28 14:15 |显示全部楼层
10可用积分
读了动态链接库方面的讲解,大多数说的都是当一个.so文件被dlopen调入内存的时候,无论多少个可执行文件去掉用它,它只打开一次,操作体系会有一个自动的计数器,当所有载入进程都结束后这个动态库就被释放。

于是我做了一个实验,实验结果和我预期的有出入,我发现.so文件每次被载入内存以后,都会有一个新的实例产生,否则无法解释我下面的结果:

源代码1: 库函数文件:
> cat f.c
#include<stdio.h>
void f(){
        static int i=0;
        i=i+1;
        printf("i=%d\n",i);
        printf("i+1=%d\n",i+1);
}

源代码2: 主函数文件:
> cat main1.c
#include<stdio.h>
#include<stdlib.h>
#include<dlfcn.h>
#include<link.h>
#include<libgen.h>
/*extern void f();*/
void * handle=0;
typedef void (*pf)(void);
pf p;
void g(){
        int k;
        k=k+1;
}
int main(void){
        int j;
        g();
        handle=dlopen("./libf.so",RTLD_LAZY);
        if(handle==0){
                printf("dlopen failed!\n";
                return 1;
        }
        p=(pf)dlsym(handle,"f";
        //f();
        (*p)();
        scanf("%d",&j);
        return 0;
}


3.make的shell文件:
> cat make.sh
#!/bin/sh
gcc -fpic -c f.c -o f.o && gcc -shared -g -o libf.so f.o && gcc main1.c -g -o main1 -L. -lf -ldl
-------------------------------------------------------------------------------------------------------------
实验结果
然后我运行main1,它打印两行信息,然后等待scanf:
> ./main1
i=1
i+1=2

我再开一个终端窗口,还是运行./main1
> ./main1
i=1
i+1=2

->我很奇怪这里的结果,既然说动态链接库在内存里面只有一个实例,那么我在第二个终端里运行main1(第一个终端的main1没有结束,停留在scanf阶段)的时候,我期望它输出的应该是i=2 i+1=3啊!目前的现象是否说明每个可执行程序都载入一个新的.so映像?

->实验2,把f()中的static int i=0移动到函数体外作为全局变量,同样的实验结果。
->实验3,把dlopen的调用去掉,直接在链接main1的时候指定-lf,同样的实验结果。

还请各位大家赐教,解释一下原因,为什么动态库并不是一个实例?(从实验结果来看,sun平台5.

谢谢!

最佳答案

查看完整内容

哈哈,要放假了,心情好。兄弟你继续happy吧,搞不懂GOT PLT可以搜搜俺以前发的帖子讲这个的。前面的兄弟已经告诉你答案了,知道什么是PIC代码吗?我建议你info gcc搜搜-fPIC、-shared了解一下。你以为有多个进程了,每个进程中虚拟地址就不一样了?搞懂了PIC代码的原理你就知道为啥是“通过一样的虚拟地址访问”了。我难得在CU上讲话这么嚣张,不过今天心情这的是好

论坛徽章:
0
发表于 2008-09-28 14:15 |显示全部楼层
原帖由 ytl 于 2008-9-28 15:26 发表


真是浪费时间,还在认为”通过同样的虚拟地址访问“

哈哈,要放假了,心情好。
兄弟你继续happy吧,搞不懂GOT PLT可以搜搜俺以前发的帖子讲这个的。
前面的兄弟已经告诉你答案了,知道什么是PIC代码吗?我建议你info gcc搜搜-fPIC、-shared了解一下。
你以为有多个进程了,每个进程中虚拟地址就不一样了?搞懂了PIC代码的原理你就知道为啥是“通过一样的虚拟地址访问”了。

我难得在CU上讲话这么嚣张,不过今天心情这的是好

论坛徽章:
0
发表于 2008-09-28 14:19 |显示全部楼层
数据有多分,代码一份

论坛徽章:
0
发表于 2008-09-28 14:21 |显示全部楼层
应该有copy on write
数据修改的时候会把数据段copy一份
代码段就只有1份

论坛徽章:
0
发表于 2008-09-28 14:24 |显示全部楼层
有一个问题想不通:如果代码只有一份,怎么处理数据在不同进程空间的逻辑地址不一样的问题?

论坛徽章:
0
发表于 2008-09-28 14:29 |显示全部楼层
原帖由 ytl 于 2008-9-28 14:24 发表
有一个问题想不通:如果代码只有一份,怎么处理数据在不同进程空间的逻辑地址不一样的问题?

LS各位都说了,这是COW的问题。
>>怎么处理数据在不同进程空间的逻辑地址不一样的问题
这是个错误的用法,动态库本身就不应该导出全局变量给应用程序使用。

论坛徽章:
0
发表于 2008-09-28 14:35 |显示全部楼层
原帖由 zx_wing 于 2008-9-28 14:29 发表

LS各位都说了,这是COW的问题。
>>怎么处理数据在不同进程空间的逻辑地址不一样的问题
这是个错误的用法,动态库本身就不应该导出全局变量给应用程序使用。


跟导出没关系,不导出也是靠逻辑地址访问的

论坛徽章:
0
发表于 2008-09-28 14:37 |显示全部楼层
cow不是关键,只是优化技巧而已

论坛徽章:
0
发表于 2008-09-28 14:39 |显示全部楼层
如果代码只有一份,它怎么去访问多份数据呢? 想不通。。。。。。

楼上说的导出全局变量给程序用的情况,不能说是一个错误,因为我在很多大型系统中都见到过这种情况(银行,电信计费等等),这种情况很普遍啊!

继续讨论!

论坛徽章:
0
发表于 2008-09-28 14:40 |显示全部楼层
原帖由 zx_wing 于 2008-9-28 14:29 发表

LS各位都说了,这是COW的问题。
>>怎么处理数据在不同进程空间的逻辑地址不一样的问题
这是个错误的用法,动态库本身就不应该导出全局变量给应用程序使用。



没有听说过这个说法
动态库的符号地址存在.got.plt,是由loader填进去的,不是绝对地址,所以不存在逻辑地址不一样的问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP