内核我用 Linux技术文

动态链接的一点小总结 《程序员的自我修养》·笔记

2015-08-22  本文已影响684人  popsheng

动态链接的一点小总结

/* Program1.c */
#include "Lib.h"
int main()
{
    foobar(1);
    return 0;
}
/* Program2.c*/
#include "Lib.h"
int main()
{
    foobar(2);
    return 0;
}
/* Lib.c */
#include <stdio.h>
void foobar(int i)
{
    printf("Printing from Lib.so %d\n",i);
}
/* Lib.h */
#ifndef LIB_H
#define LIB_H
void foobar(int i);
#endif
- 程序很简单,两个程序的主模块Program1.c和Program2.c分调用Lib.c里面的foobar()函数执行相应的操作。
- 接下来我们使用gcc将Lib.c编译成为一个共享对象文件(即动态链接文件)如下:  
`gcc -fPIC -shared -o Lib.so Lib.c`  
其中,`-shared`是表示产生共享对象的参数,这样我们就得到了一个Lib.so文件。
- 接着,我们编译链接Program1.c和Program2.c文件:  
`gcc -o Program1 Program1.c ./Lib.so`  
`gcc -o Program2 Program2.c ./Lib.so`  
这样我们就得到了两个程序**Program1**和**Program2**,整个编译以及链接过程大致如下:
![](http://7xl3j2.com1.z0.glb.clouddn.com/cxy-9.jpg)
【引入模块module的概念】在动态链接下,一个程序被分成若干个文件,有程序的主要部分,即可执行文件(Program1),也有程序所依赖的共享对象(Lib.so),很多时候,我们也把这些部分称为模块,即动态链接下可执行文件和共享对象都可以看作是程序的一个模块。
- 当链接器将Program1.o链接成可执行文件的时候,这个时候链接器必须确定Program1.o所引用的foobar()函数的性质,如果该函数是一个定义在某个动态共享对象中的函数,那么链接器就会将这个符号的引用标记为一个动态链接的符号,不对他进行地址重定位,把这个过程留到装载的时候再进行。判断函数是静态符号还是动态符号也简单,Lib.so保存了完整的符号信息。

【需要注意的是】共享对象的最终装载地址在编译的时候是不确定的,而是在装载的时候,装载器根据当前地址空间的空闲状况,动态分配一块足够大小的虚拟地址空间给相应的共享对象。这样的话,关于共享对象的地址就会出现问题,下面会给出问题以及对应的解决方案。


通过上面原理的了解,接下来我们考虑一下动态链接的基本实现过程

上一篇下一篇

猜你喜欢

热点阅读