操作系统是怎么实现动态链接库被多个进程共享的
操作系统是如何实现动态链接库被多个进程共享的
第一个程序A,链接了共享库比如 la.so,这时A的可执行文件和共享库 la.so都会被读进内存;如果第二个程序B也链接了 la.so,这时B的可执行文件被读入内存,系统是怎么知道 la.so已经在内存中了呢(是否在内核或其他地方具有某种记录)?
另外系统共享库的数据部分由进程独享,而代码部分可以多个进程共享,理论上这时只要把进程B的虚拟地址空间映射到 la.so的指令部分存放的物理内存就可以了,系统是怎么记录 la.so 的物理内存地址呢? 这个过程是由加载器还是动态链接器或者其他的成分来完成呢?
------解决思路----------------------
重定位是由于程序运行时被加载到的地址和编译链接时指定的地址不同时才可能会发生的,由于可执行程序通常是第一个被加载的模块,加载的时候整个虚拟内存空间几乎都是空的,所以一定可以把它加载到链接的时候指定的那个地址上,因此也就不需要重定位,既然不需要重定位就没有必要把它编译成位置无关的代码了。
至于说程序中调用其它动态模块的函数,那是另外一个故事了,在 windows 中这个是通过导入表来完成的,在 linux 中有动态链接机制,他们都是在加载的时候通过符号查找来确定地址的,并不是通过重定位... 重定位只是解决模块内部引用自己的全局变量导致的问题。
第一个程序A,链接了共享库比如 la.so,这时A的可执行文件和共享库 la.so都会被读进内存;如果第二个程序B也链接了 la.so,这时B的可执行文件被读入内存,系统是怎么知道 la.so已经在内存中了呢(是否在内核或其他地方具有某种记录)?
另外系统共享库的数据部分由进程独享,而代码部分可以多个进程共享,理论上这时只要把进程B的虚拟地址空间映射到 la.so的指令部分存放的物理内存就可以了,系统是怎么记录 la.so 的物理内存地址呢? 这个过程是由加载器还是动态链接器或者其他的成分来完成呢?
------解决思路----------------------
重定位是由于程序运行时被加载到的地址和编译链接时指定的地址不同时才可能会发生的,由于可执行程序通常是第一个被加载的模块,加载的时候整个虚拟内存空间几乎都是空的,所以一定可以把它加载到链接的时候指定的那个地址上,因此也就不需要重定位,既然不需要重定位就没有必要把它编译成位置无关的代码了。
至于说程序中调用其它动态模块的函数,那是另外一个故事了,在 windows 中这个是通过导入表来完成的,在 linux 中有动态链接机制,他们都是在加载的时候通过符号查找来确定地址的,并不是通过重定位... 重定位只是解决模块内部引用自己的全局变量导致的问题。