关于动态链接学习中的小结

来源:互联网 发布:c语言getchar putchar 编辑:程序博客网 时间:2024/06/10 05:14

知识来源:程序员的自我修养:

//////////////////////////////////////////////////

静态链接是将一块一块的.o目标文件,拼到一起,也就是将调用其他模块的函数进行函数地址引用重定位,最终生成一个可执行程序

而且对于静态链接的可执行文件来讲,整个进程只有一个文件要被映射,那就是可执行文件本身

////////////////////////////////////////////////

动态两个字体现在哪些地方:

1.动态链接,在链接的时候对调用的其他模块函数,链接器会将这个符号的引用标记为一个动态链接的符号,不对它进行地址重定位,把这个过程留到装载时再进行。

2.可执行文件,及它所依赖的共享目标文件包括c的库模块libc,动态连接器(一个特殊的共享文件——自举)都会被映射进程的虚拟地址空间;

readelf 工具可以查看.so文件的装载属性

注:3.动态链接模块的装载地址是从地址0x00000000开始的;共享对象的最终装载地址在编译的时候是不确定的,是在装载时根据当前地址空间的空闲状况,动态分配一块足够大小的虚拟地址空间给相应的共享对象。

共享对象在编译的时候不能假设自己在进程虚拟地址空间中的位置,也即共享对象可以在任意地址加载

而可执行文件可以确定,可执行文件是第一个被加载的文件,他可以选择一个固定空闲的地址,linux下为0x08040000,windows下为0x0040000

//////////////////////////////////////////////////

地址无关代码技术:

-fPIC

将指令中那些需要被修改的部分分离出来,跟数据部分放在一起,这样指令部分就可以保持不变(地址无关 ),而数据部分可以在每个进程中拥有一个副本。

PIC使.so文件的代码段变为真正意义上的共享
如果不加-fPIC,则加载.so文件的代码段时,代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于 这个.so文件代码段和数据段内存映射的位置.
http://blog.const.net.cn/a/17195.htm
这是去掉-fPIC的报错:
/usr/bin/ld: ./Accelerometer.o: relocation R_X86_64_32 against `typeinfo for aocs_stream_wrap::stream_error' can not be used when making a shared object; recompile with -fPIC
./Accelerometer.o: could not read symbols: Bad value
relocation R_X86_64_32 against (`typeinfo(每一个class所关联的type_info object 用以支持runtime type identification ,RTTI也放在虚函数列表中第一个slot) for aocs_stream_wrap::stream_error') can not be used (when making a shared object);

无法重定位?为什么恰恰是这一段数据对象无法重定位?????????????????????????????????????????????

一下午时间,勉强很粗略地将本书第七章看了一次,还是很多不解和雾水。。。

隔段时间后,还要继续看,反复看

在EmulatorDll解决方案的各个工程中,为了移植到linux我做了很多将MFC下的dllimport 这种导出动态库中的外部接口函数宏注释掉的工作,那么我的疑问是,这样注释掉了之后是否仍然可以在外部工程中调用其他工程的外部接口函数,依据本书216页的底部的例子,可以看出,答案是肯定的,不需要加额外的宏,但是有一个必须注意的问题是在主工程主函数中,不能有重名的函数,否则会被覆盖掉。这些符号最终都是在全局符号表中的(装载共享对象的过程)。

通过查看解决方案中的子工程的函数,确实有重名的现象,但是主工程调用的时候都是通过具体的对象对这些public函数的访问,所以不会被覆盖






0 0
原创粉丝点击