《程序员的自我修养》动态链接章
动态链接程序运行时地址空间分布:
在可执行文件中有各种符合和函数的地址,这个地址实际上是进程的虚拟地址。.so文件中也有各种符号地址以及装载地址等。但是.so文件中的这个地址是不确定的,即是不固定的。只有在这个so文件被装载时才会解析出一个合理的装载地址,从而装载进物理内存。(这里的装载地址和符号地址实际上都是进程的虚拟地址)。那么问题来了,为什么so文件的符号地址和装载地址不能是固定的,(假设so文件装载地址为0x88),这是因为so文件会被多个模块共享。假如A和B模块共享so,那么A和B访问0x88的时候将访问到相同的物理内存地址即so在物理内存的地址,这没有问题。但是如果C模块不使用so文件,则C模块也可以访问到0x88,不过这时候0x88将被映射到另一个没有so的物理地址,这也没有问题。问题在于,当一个进程里具有A C或A B个两个模块时会怎么样呢(这种情况下显然C也是个so文件),显然这个时候0x88冲突了。所以解决这种问题的办法就是so文件的地址不能固定,只有在装载时才解析出装载的进程地址。
现代动态链接的意义要符合两个要点:
1、 动态的加载,就是当这个运行的模块在需要的时候才被映射入运行模块的虚拟内存空间中,如一个模块在运行中要用到mylib.so中的myget函数,而在没有调用mylib.so这个模块中的其它函数之前,是不会把这个模块加载到你的程序中(也就是内存映射),这些内容在内核中实现,用的是页面异常机制(我可能在另一篇文章中提到这个问题)。
2、 动态的解析,就是当要调用的函数被调用的时候,才会去把这个函数在虚拟内存空间的起始地址解析出来,再写到专门在调用模块中的储存地址内,如前面所说的你已经调用了myget,所以mylib.so模块肯定已经被映射到了程序虚拟内存之中,而如果你再调用mylib.so中的myput函数,那它的函数地址就在调用的时候才会被解析出来。