- 论坛徽章:
- 0
|
现有一静态库(libdep.a),定义如下函数:
void func(void)
{
staticint inited =0;
if(!inited)
{
do_init();
inited =1;
}
}
有两个动态库,分别命名为libref1.so 和 libref2.so,这两个动态库中分别调用了静态库libdep.a中的func函数. 动态库在编译的时候链接了静态库libdep.a。
libref1.so中
void ref1_func(void)
{
func();
}
libref2.so中
void ref2_func(void)
{
func();
}
应用程序main函数中又调用动态库中的这两个函数:
int main(int argc,char**argv)
{
ref1_func();
ref2_func();
return0;
}
程序运行发现 do_init()只被执行了一次。
但是如果在应用程序用,使用dlopen/dlsym来加载动态库
int main(int argc,char**argv)
{
void* handle1,*handle2;
void (*ref1_func)(void);
void (*ref2_func)(void);
handle1 = dlopen("libref1.so",RTLD_LAZY);
ref1_func = dlsym(handle1,"ref1_func");
handle2 = dlopen("libref2.so",RTLD_LAZY);
ref2_func = dlsym(handle2,"ref2_func");
ref1_func();
ref2_func();
dlclose(handle1);
dlclose(handle2);
return0;
}
程序运行发现do_init()被执行了两次。
问题1:两个动态库中属于静态库(libdep.a)的部分被合并了吗?
(也就是如果一个静态库被链接到100个动态库中,而一个进程运行时加载了这些动态库,忽略lazy flag,那么进程空间内是有100份静态库的拷贝、还是只有1份呢?我感觉应该是100份。)
问题2:如果确实有两份,静态变量inited共享同一份拷贝吗(否则怎么理解动态链接只运行一次的现象呢)?
(有人说so实际在内存中只装载一次,而各个进程加载它时将代码段部分映射过去,而数据段各个进程各不相同,但是在ELF中静态变量inited作为bss section的一部分同属于data segment啊。难道加载器特别处理bss部分?)
问题3:是不是如同augustusqing所说,“生成的两个so,每个so里面有静态库的拷贝,但记录的符号名字是同名的。当他们直接以-l方式链接进同一个进程的时候,链接和运行过程中,只需要在任何一个so里找到了静态库的符合,程序就开跑,运行的是同一份静态库。所以只执行一次”。也就是说ELF文件不会区分来自不同库的相同符号?
困扰我好几天,多谢了众大侠啦。
[ 本帖最后由 zangkannt 于 2009-4-9 12:51 编辑 ] |
|