静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库;动态库(.so或.sa):程序在运行的时候才去链接共享库的代码,多个程序共享使用库的代码。
以下为动态库的运行原理:
一个与共享库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码;在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该共享库中复制到内存中,这个过程称为动态链接(dynamic linking);共享库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份共享库被要用到该库的所有进程共用,节省了内存和磁盘空间。
生成静态库:
现在将hello_fn.c模块生成库,库可以认为是个归档文件,将.o文件打包生成库。
见以下说明
#先生成.o文件,别忘了-c,若不加-c就是生成可执行文件了
gcc -Wall -c hello_fn.c -o hello_fn.o
#ar是归档文件,rcs(replace and create)
ar rcs libhello.a hello_fn.o
#两种方式使用libhello.a
(1)
gcc -Wall main.c libhello.a -o main
(2)
#或(注意提示错误,因为默认情况下不会在当前目录下查找库)
gcc -Wall main.c -o main -lhello
#正确(-L.表示库文件的位置在这地下,否则在系统的目录下搜索)
gcc -Wall -L. main.c -o main -lhello
#说明下,这时生成main可执行程序后,若删掉libhello.a静态库后,也不会影响,因为静态库是链接到可执行文件中了
库路径搜索
按顺序来:
- 从左到右搜索-I(指定头文件的目录) -L指定的目录(指定库的目录)
- 由环境变量指定的目录(环境变量可在~/.bash_profile(对当前用户生效)下设置LIBRARY_PATH(静态库路径)或C_INCLUDE_PATH(c头文件),CPLUS_INCLUDE_PATH(c++头文件)),或/etc/profile(对所有用户生效)
- 由系统指定的目录
生成动态库
shared: 表示生成共享库格式
fPIC:产生位置无关码(position independent code)
(解释下:允许它在任何位置加载)
库名规则:libxxx.so
gcc -shared -fPIC hello.o –o libhello.so
使用共享库
编译选项
l:链接共享库,只要库名即可(去掉lib以及版本号)
L:链接库所在的路径.
示例:
gcc main.o -o main –L. -lhello
如何解决经常找不到库的问题共享库运行时需要的设置
- 拷贝.so文件到系统共享库路径下
一般指/usr/lib - 更改LD_LIBRARY_PATH(动态库),LIBRARY_PATH(静态库) (在配置文件~/.bash_profile下(当前用户下) )
- ldconfig(全局的)
配置ld.so.conf(/etc/ld.so.conf下配置库),之后再调用ldconfig更新ld.so.cache即可
可以用ldd main(可执行程序名)查看链接的库