赞
踩
在程序翻译的链接阶段,其实就是把一堆.o
文件链接在一起形成.exe
文件。如果一个程序中需要链接很多个.o
文件,那么这些.o
文件就需要被打包才方便管理,**库文件本质就是把.o
文件打包。**库文件是一种提高开发效率的手段。
库有动态库和静态库之分,不同的操作系统的动静态库后缀也不同:
动态库 | 静态库 | |
---|---|---|
Linux | .so | .a |
Windows | .dll | .lib |
对于静态库,使用静态库形成可执行程序后,静态库被加载到了可执行程序的代码里,不需要让系统知道静态库在哪里;但对于动态库,由于动态库不加载到可执行程序里,而是动态加载到内存中,所以使用动态库要告诉系统动态库在哪(因为是系统来加载动态库)。
动态库在编译时代码不会被复制到可执行文件中,而是在运行时由操作系统动态加载到内存中。而静态库在编译时代码会被完整地复制并链接到可执行文件中。使用动态库的可执行程序共用同一个库,而使用静态库的可执行程序中都单独有静态库的拷贝。
链接:
我们的程序需要与某些库结合才能执行,与库结合的过程就是链接。每个语言都要有自己的标准库,在安装开发环境的时候就需要安装语言的标准库和头文件。
优点:
1.更加节省内存并减少页面交换。
2.库文件与程序文件独立,只要输出接口不变,更换库文件不会对程序文件造成任何影响,因而极大地提高了可维护性和可扩展性。
3.不同编程语言编写的程序只要按照函数调用约定就可以调用同一个库函数。
4.适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。
缺点:
1.运行时依赖,否则找不到库文件就会运行失败。
2.运行加载速度相较静态库慢一些。
3.需要对库版本之间的兼容性做出更多处理。
静态库
优点:
1.运行加载速度块。
2.使用静态库的可执行程序一旦形成,就与库无关。
缺点:
1.有多少个程序依赖静态库,静态库在代码中就有多少份拷贝,造成资源浪费。
2.修改静态库代码后,需要重新形成所有依赖这个库的可执行程序,造成时间浪费。
gcc/g++需要知道库的路径才能找到库,如果不把第三方库安装到系统的库目录里,gcc/g++就需要有头文件和库的所在目录路径才能找到找到第三方库,其中头文件只需要传它们所在的目录即可,但库文件除了给出目录的路径还需要给出库的具体名字,且要删去lib
和.a
只保留中间的部分。
gcc链接第三方库的选项:
gcc [file] -
I
[头文件路径] -L [库文件路径] -l [库文件名] -I
表示指定用户自定义头文件路径 -L表示用户自定义库文件路径 -l表示执行确定的第三方库名称
#inlcude<>
中的<>
表示在系统的库目录中查找。实际上代码文件中的#inlcude<>
中就已经给出了头文件的具体名字,所以不用在gcc的时候加上头文件的名字。如果将<>
替换成""
,且里面的内容不是头文件的名字,而是头文件的路径加名字,那么gcc的时候甚至可以不写头文件的路径。
链接静态库:
gcc默认链接动态库,如果gcc没有-static
选项,且只提供.a
,那么就会静态链接.a
库,其他库正常动态链接;如果有-staitc
选项,它表示链接的所有库都必须提供对应的静态库,否则报错。
所有的系统动态库都在lib64目录下存储,解决系统找不到动态库的一个办法就是把第三方库拷贝到该目录下,且系统与该目录的动态库是松耦合关系,只要动态库在目录里就能直接被找到。
一般不推荐把第三方库直接安装到lib64目录下,但是可以在lib64目录里建立一个第三方库的软链接,这种方法在实践中也常用到。
可以通过LD_LIBRARY_PATH
设置临时环境变量,让系统在找寻库的时候在特定的路径下查找,添加环境变量的方式为:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:[库路径]
该环境变量在每次系统登陆时都会刷新,不能永久保存。
如果想永久保存设置的环境变量,可以修改.barshrc环境变量配置文件,让环境变量永久生效。
最推荐的方式是设置新增动态库搜索的配置文件
先以管理员权限进入这个目录:
/etc/ld.so.conf.d
在该路径下添加一个文件:
touch [name].conf
用vim打开刚刚新建的.conf
文件,在配置文件里将动态库的路径拷贝进去,然后使用ldconfig
命令使配置文件生效。
当进程被加载到内存时,它对应的动态库并不会随之加载进内存,而是当进程要使用动态库里的内容时,页表发现动态库不存在,发生缺页中断,于是OS到磁盘中找到动态库将它加载到内存中。在进程内部,动态库的代码被放入在地址空间中的一块空间中(静态库也在这);而在物理地址中,进程的代码和动态库独立(静态库直接加载到进程的代码中),使得动态库像一个独立的进程存在于内存中。当其他进程要使用该动态库时,页表发现动态库已经在内存中了,于是就直接映射,不允许再次将动态库加载到内存中,即多个进程共享同一个动态库。
当进程使用动态库中的某个函数时,库里的函数本身就有地址,而地址空间中本身也有一套地址。所以进程不能直接使用库中的地址,它本质是将库起始位置的地址(称为偏移量),加上库中函数的地址,最终组成进程访问库中函数的地址。
ls /lib64
gcc -c [file] 形成静态.o
gcc -fPIC -c [file] 形成动态.o -fPIC表示与产生位置无关码(position independent code)
静态库:
ar -rc [file].a *.o rc表示(replace and create)存在就替换,不存在就创建
动态库:
gcc可以直接用来形成动态库,因为实际使用中动态库的使用频率比静态库大
gcc -shared *.o -o [lib].so -shared表示形成共享库格式(其实就是告诉gcc不要形成可执行程序)
gcc/g++不认识第三方库,所以在编译的时候要加-l
选项,但要注意库文件一般以libxx.a
命名,但-l
后面的选项要删去lib
和.a
只保留中间的部分
gcc [file] -l [lib]
ldd [可执行程序]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。