28th
动态链接库就像内存中的共享单车,大家都用这一辆车子,谁需要谁加载,而不是给每个人都配备一辆。
以 C 标准库为例,C 标准库的大小在 1M 以上,Linux 中使用标准输入输出的程序得有上千个,假设同时在内存中运行的程序有 100 个,那如果每个程序都加载一份 C 标准库到内存中的话,100M 内存就出去了。而如果使用动态链接库,只需加载一份就可以了。
由于动态链接库为大家所共享,所以他必须是地址无关的。
为了实现地址无关,动态链接库内部的变量和函数调用使用的都是相对地址。
还有一个问题,应用程序在调用动态链接库中的函数时,可能会有数据的输入和输出,对动态链接库来说,这些数据是外部数据,他在被链接的时候并不知道这些数据的地址。为了解决这个问题,引入了程序链接表(PLT,Procedure Link Table)和全局偏移表(GOT,Global Offset Table),应用程序如果要调用动态链接库里的函数,就去程序链接表里面找对应的地址。GOT 中记录了所有链接动态链接库的程序使用的数据,因为动态链接库在内存中只有一份,而不同的程序用到的数据是不一样的,所以当程序A调用动态链接库时,后者就去 GOT 中查找程序A对应的数据。
PLT 实际上起到了延迟绑定的作用,程序在链接的时候虽然会把动态链接库链接上,但是可能在程序运行时并不会去调用,那么这时就不必在 GOT 中生成数据。只有当程序调用动态链接库时,才会去 PLT 中查找相应的地址,这个时候再往 GOT 里面写入数据。
Linux 下,这些动态链接库是 .so 文件,而 Windows 下的动态链接库就是 .dll 文件。
——《极客时间-深入浅出计算机原理 第10讲》总结
Last updated
Was this helpful?