动态链接库
什么是动态链接库
以下均为本人自己的理解,不一定正确,但是大致应当是差不多的
在很久之前,没有库的概念,每一次写代码都是在从头造轮子
后来,人们发现某一些功能是大部分程序里面都要用到的、共通的,且和具体程序没有该关系,例如向控制台打印一个字符等。于是,为了减少写代码的成本,人们把这些实现共通功能的代码汇聚起来,每一次需要使用的时候就用include
或者import
之类的方法去引用它。
再后来,这类代码的量越来越大。这导致了两个问题:1,每一次编译的消耗越来越多;2,实际上并不会用到所有的代码,多出来的那部分成了浪费。这部分代码本来就和具体的程序没有关系,但是每一个新程序都不得不编译它们,即使只是使用简单的打印函数也要把所有代码都包括进去。那么只是包括一部分代码呢?仍然没有从根本上解决问题。人们最希望的是这部分代码可以不用再进行编译、可以直接整合到一个新的程序里面。
于是,为了解决这个问题,人们发明了静态链接库。
首先,将所有的代码分别编译为目标文件,再将这些目标文件压缩为一个文件,并赋予这些文件一个目录。接下来,在编译的时候,就可以按需获取这些已经编译好了的部分并嵌入到程序中。例如,要使用某个函数foo,在链接的时候,在静态链接库目录中找到这个foo的位置,然后把它塞到程序里面。
这样子,既解决了重复编译的问题,也解决了可执行程序的规模太大的问题。
但是这样子做还是会有不足的地方:某一些代码的执行实在是太频繁了,以至于几乎所有的程序里面都会内嵌了这么一个代码。因此,同一份代码在内存上就会存在成百上千的拷贝——而这些内存本来可以拿来干一些更有用的事情,例如跑更多的程序。第二个更为棘手的地方是,原来的静态链接库要是出bug了,那么,所有有包含这部分代码的程序都必须要重新编译一次——至于哪些程序包含这些代码而其他的没有,在写完之前程序员和神都知道,写完之后大概只有神知道了。
因此,为了弥补这种不足,出现了动态链接库。
所谓动态链接库,是指它是动态链接的——要用到就链接一份,不用就不链接。
所有的此类可复用的代码放在一个动态链接库里面,在内存中占有一部分位置。当有程序要用到里面的一部分函数的时候,就去那里找自己想要的方法。这样子,此类代码在内存中就只有一个备份了,而且当需要更新bug的时候,仅需要简单地更新动态链接库的版本就可以了。
动态链接库一定比静态链接库来得好吗?不一定。
动态链接库是在运行的时候才链接上去的,程序在用到这部分东西的时候还必须停下来链接一下(也就是找一下这部分代码放哪里了)然后才能接着走。
另外,系统还必须运行着一个动态链接器,来帮助我们的程序找到它需要的代码。
但是,在硬件发展得这么快的今天,这点损耗早已微不足道。
GOT、PLT
参考博文:https://blog.youkuaiyun.com/u011987514/article/details/67716639?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control
既然程序需要使用动态链接库,那么就必须要知道自己需要使用动态链接库中的哪些部分,以便在装载的时候精准地把相应部分链接到它的地址空间上。将这些和地址相关的部分放在数据段里面,称之为GOT(Gloabl Offset Tab