库的概念
- 库是二进制文件,包含的代码可被调用
- 标准C库、数学库、线程库……
- 库有源码,可下载后编译;也可以直接安装二进制包
- 系统默认库的位置
/lib
/usr/lib
- 库是事先编译好的,可以复用的代码
- win和Linux库不兼容
- LInux下包含静态库和共享库
静态库
优缺点
- 编译(链接)时把静态库中的相关代码复制到可执行文件中
- 程序 中以包含代码,运行是不再需要静态库
- 程序运行时无须加载库,运行速度更快
- 占用更多磁盘和内存空间
- 静态库升级后,程序需要重新编译链接
静态库的创建
- 确定库中函数的功能、接口
- 编写库源码hello.c
#include <stdio.h>
void hello(void)
{
puts("量子孤岛");
return;
}
- 编译生成目标文件
$ gcc -c hello.c -Wall
- 创建静态库hello
$ ar crs libhello.a hello.o
注意:静态库名称lib**.a是固定格式,**是库名
- 查看库中符号
$ nm libhello.a
>>>>>
hello.o:
0000000000000000 T hello
U puts
链接静态库
- 编写应用程序
#include <stdio.h>
void hello(void);
int main()
{
hello();
return 0;
}
- 编译test.c并链接静态库libhello.a
$ gcc -o test test.c -L. -lhello
-l:指定链接库的名称
-L:指定链接库的路径
编译器默认链接C库
删除库程序依然能运行,因为静态库代码会被复制到程序中。
共享库
特点
- 编译(链接)时仅记录用到哪个共享库中的哪个符号,不复制共享库中相关代码
- 程序不包含库中代码,尺寸小
- 多个程序可共享同一个库
- 程序运行时才会加载库
- 库升级方便,无须重新编译程序
共享库的创建
1. 确定库中函数的功能、接口
2. 编写库源码hello.c bye.c
#include <stdio.h>
void bye(void)
{
puts("bye!");
}
3. 编译生成目标文件
$ gcc -c -fPIC hello.c bye.c -Wall
-fPIC:生成位置无关代码
4. 创建共享库common
$ gcc -shared -o libcommon.so.1 hello.o bye.o
说明:
.so:表示共享库文件,.数字——表示库的版本
命名规则:lib<库名>.so.x
5. 为共享库文件创建链接文件
$ ln -s libcommon.so.1 libcommon.so
目的就是编译器在编译时能找到共享库
版本号的好处就是一个库可以有不同的版本,.so指向哪一个文件就调用哪一个库
为库提供头文件,更加规范一些
$ gcc -o test test.c -L. -lcommon
这里和静态库是一样的,怎么区分呢?
gcc会优先链接共享库,如果不存在则链接静态库,如果静态库也没有,就会报错。
加上-static选项,即为直接链接静态库
出现:
./test: error while loading shared libraries: libcommon.so: cannot open shared object file: No such file or directory
因为当前目录没有在系统的搜索目录中
执行:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
如何找到共享库?
- 把库拷贝到/usr/lib和/lib目录下
- 在LD_LIBRARY_PATH环境变量中添加库所在路径,缺点是重开shell失效
- sudo vim /etc/ld.so.conf.d/*conf文件,sudo ldconfig刷新
就是添加新文件,随便起名字,然后把库的目录添加进去
/home/linux/io/lib/share
然后刷新