文章目录
一、什么是库
- 库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。
- 库是特殊的一种程序,编写库的程序和编写一般的程序区别不大,只是库不能单独运行。
- 库文件有两种,静态库和动态库(共享库),区别是:静态库在程序的链接阶段被复制到了程序中;动态库在链接阶段没有复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。
- 库的好处:1. 代码保密 2. 方便部署和开发
二、静态库
1、命名规则
- libxxx.a
lib :前缀(固定)
xxx :库的名字,自己起
.a :后缀(固定)
2、制作
实验代码
(1)gcc
获得 .o
文件
nowcode@nowcode:~/test01/calc$ gcc -c add.c div.c mult.c sub.c
nowcode@nowcode:~/test01/calc$ tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
(2)将 .o
文件打包,使用 ar
工具(archive)
nowcode@nowcode:~/test01/calc$ ar rcs libcalc.a add.o div.o mult.o sub.o
nowcode@nowcode:~/test01/calc$ tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── libcalc.a
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
3、使用
(1) 将 libcalc.a
复制到 library
下的 lib
nowcode@nowcode:~/test01/calc$ cp libcalc.a ../library/lib/
nowcode@nowcode:~/test01/calc$ cd ..
nowcode@nowcode:~/test01$ cd library
nowcode@nowcode:~/test01/library$ tree
.
├── include
│ └── head.h
├── lib
│ └── libcalc.a
├── main.c
└── src
├── add.c
├── div.c
├── mult.c
└── sub.c
(2)使用 gcc
编译 main.c
文件
关于gcc编译参数可以参考文章:Linux系统 gcc工作流程和gcc编译参数
nowcode@nowcode:~/test01/library$ gcc main.c -o app -I ./include/ -l calc -L./lib/
nowcode@nowcode:~/test01/library$ ./app
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667
三、动态库
1、命名规则
- libxxx.so
lib :前缀(固定)
xxx :库的名字,自己起
.so :后缀(固定)
在Linux下是一个可执行文件
2、制作与使用
(1)gcc
获得 .o
文件,得到和位置无关的代码
nowcode@nowcode:~/test02/calc$ gcc -c -fpic add.c div.c mult.c sub.c
nowcode@nowcode:~/test02/calc$ tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
(2)gcc
得到动态库
nowcode@nowcode:~/test02/calc$ gcc -shared add.o div.o mult.o sub.o -o libcalc.so
nowcode@nowcode:~/test02/calc$ tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── libcalc.so
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
(3)使用动态库
nowcode@nowcode:~/test02/calc$ cp libcalc.so ../library/lib/
nowcode@nowcode:~/test02/calc$ cd ..
nowcode@nowcode:~/test02$ cd library
nowcode@nowcode:~/test02/library$ tree
.
├── include
│ └── head.h
├── lib
│ └── libcalc.so
├── main.c
└── src
├── add.c
├── div.c
├── mult.c
└── sub.c
nowcode@nowcode:~/test02/library$ ./app
./app: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory
3、加载失败的原因
- 静态库:GCC进行链接时,会把静态库中代码打包到可执行程序中
- 动态库:GCC进行链接时,动态库的代码不会被打包到可执行程序中
- 程序启动之后,动态库会被动态加载到内存中,通过
ldd(list dynamic dependencies)
命令检查动态库依赖关系 - 如何定位共享文件呢?
当系统加载可执行代码时候,能够知道其依赖的库的名字,但是还需要知道绝对路径。此时就需要系统的动态载入器来获取绝对路径。对于elf格式的可执行文件,是ld-linux.so
来完成的,它先后搜索elf文件的DT_RPATH段 ⟶ \longrightarrow ⟶ 环境变量LD_LINRARY_PATH ⟶ \longrightarrow ⟶ /etc/ld.so.cache文件列表 ⟶ \longrightarrow ⟶ /lib/,/usr/lib目录找到库文件后载入内存
4、解决加载失败的方法
a. 配置环境变量DL_LIBRARY_PATH
(1)暂时配置
nowcode@nowcode:~/test02/library$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/nowcode/test02/library/lib
nowcode@nowcode:~/test02/library$ echo $LD_LIBRARY_PATH
:/home/nowcode/test02/library/lib
nowcode@nowcode:~/test02/library$ ./app
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667
(2)用户级配置
打开.bashrc
文件
nowcode@nowcode:~$ vim .bashrc
在.bashrc
文件最后加入下面语句
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/nowcode/Linux/lesson06/library/lib
在加入后,要运行一下.bashrc
文件
nowcode@nowcode:~$ . .bashrc
(3)系统级配置
打开 /etc/profile
文件
nowcode@nowcode:~/test02/library$ sudo vim /etc/profile
在 /etc/profile
文件最后加入下面语句
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/nowcode/Linux/lesson06/library/lib
在加入后,要运行一下 /etc/profile
文件
nowcode@nowcode:~/test02/library$ . /etc/profile
b. 处理/etc/ld.so.cache文件列表
打开/etc/ld.so.conf
文件
nowcode@nowcode:~$ sudo vim /etc/ld.so.conf
在 /etc/profile
文件加入下面语句
/home/nowcode/test02/library/lib
更新/etc/ld.so.cache
文件列表
nowcode@nowcode:~$ sudo ldconfig