1.共享代码
随着软件开发的发展,人们发现很多应用的代码是相同的,也就是说这些代码可以被共享,因此,人们提出了静态库和动态库两种方案来解决代码共享的问题。
2.静态库
静态库,顾名思义,它是静态的,也就是说它不会被动态编译,它只会静态编译,节省了编译时间,提高了编译速度。同一份静态库,可以被多个程序进行编译,也就实现了代码的复用共享。
3.动态库
动态库,就是程序应用启动的时候,动态加载的,因为它一般是在系统运行的时候就已经运行的动态库,因此其它应用可以直接使用它,并且同一个动态库可以被多个应用共享使用,在系统中对于一个动态库只会存在一份,这大大节省了内存空间,大大提升了系统的性能。
在linux系统中,动态库一般以.so形式命名,表示share object。
很多时候,你很难知道一个应用需要哪些动态库,不过我们有个工具ldd可以帮助你查看一个应用需要哪些动态库。
如果一些动态库没有找到的话,程序就无法正常运行,这也是你会看到很多程序启动的时候提示缺少xx.so的原因。
如果你的程序需要xx.so动态库,而系统路径中没有它的话,你可以通过LD_LIBRARY_PATH 将你需要的动态库添加到系统路径中。
查看一个文件使用了什么连接器可以使用file命令,一般程序都会使用/lib64/ld-linux-x86-64.so.2这个文件,而这个文件其实会指向一个ld-2.xx.so文件。
4.动态加载器ld.so
在linux系统中,动态库都是通过ld.so来进行管理的,它首先会根据应用的编译信息查找相对或者绝对路径来查找动态库,然后就会通过环境变量LD_LIBRARY_PATH来查找动态库,最后它会根据/etc/ld.so.cache缓存来查找动态库。
因此,当我们像系统中添加一个动态库的时候我们有两种方式,一种是直接放入到/usr/lib64文件夹里面,不过这需要你有root权限,第二种就是通过LD_LIBRARY_PATH配置我们的动态库路径。
5.程序引入动态库
在程序编译的时候,我们可以通过指定编译参数来引入动态库。
例如,当我们使用gcc来进行编译的时候,我们可以通过-l来表示链接库名称,通过-Ldir来指定动态库路径。 当我们使用g++来进行编译的时候,-L可以用来指定动态库的路径,进行程序动态库的链接。
6.总结
人们为了减少冗余代码,提出了共享库的概念,在链接的时候和程序一同打包成一个可执行文件的这个库就是静态库,反之,在链接的时候不将动态库打包进可执行文件,只是标记运行需要此共享库,这就是动态库。
静态库是同程序一同打包的,因此它不需要环境的依赖,而动态库是程序执行时候需要引用的,因此它对环境有依赖,这也是为什么很多依赖动态库的文件执行的时候报错缺少动态库的原因,那是操作系统缺少对应的动态库导致的。
静态库增大了程序的体积,同时多个程序对相同静态库的链接也占用了大量的内存,因此,才有了动态库的出现,可以说两者都是为了解决代码共享复用的问题,而且两者是相辅相成的关系。