静态库和动态库

静态库和动态库的制作和使用

库: 二进制文件, 由源码编译而来

库制作出来后如何给用户使用: (1) 头文件; (2) 制作出的库

静态库优点:

  • 静态库被打包到应用程序中, 加载速度快
  • 发布程序无须提供静态库, 移植方便
    静态库缺点:
  • 浪费系统资源, 浪费内存, 不推荐使用的原因
  • 更新, 部署, 发布麻烦

动态库

  • 动态库没有被打包进二进制可执行程序中
  • 动态库不会被加载, 当程序调用动态库中的函数时, 动态库才会加载
  • 程序运行之前会先判断动态库是否存在, 通过动态连接器: ls.so来判断

优点:

  • 可实现进程间资源共享
  • 程序升级简单
  • 程序员可控制何时加载动态库

缺点:

  • 加载速度比静态库慢
  • 发布程序需要提供依赖的动态库

静态库

静态库命名规则: lib+Name+.a, 例如libtest.a

静态库的制作:
  (1)将.c文件生成.o文件: gcc *.c -c, 后面加-g选项没意义, gdb时没有源码
  (2)将.o文件打包: ar rcs libxxx.a *.c
静态库的使用: -I指定库目录; -l指定库, 库名要去掉lib和后缀.a

zyb@server:~/dir_test/src$ vim *.c -O
#include "head.h"                |#include "head.h"                |#include "head.h"                |#include "head.h"
                                 |                                 |                                 |
int add(int a, int b) {          |int div(int a, int b) {          |int mul(int a, int b) {          |int sub(int a, int b) {
    int result = a + b;          |    int result = a / b;          |    int result = a * b;          |    int result = a - b;
    return result;               |    return result;               |    return result;               |    return result;
}                                |}                                |}                                |}
zyb@server:~/dir_test/src$ ls
add.c  div.c  mul.c  sub.c
zyb@server:~/dir_test/src$ gcc *.c -c -I ../include/
zyb@server:~/dir_test/src$ ls
add.c  add.o  div.c  div.o  mul.c  mul.o  sub.c  sub.o
zyb@server:~/dir_test/src$ ar rcs libmycal.a *.o	# 静态库打包
zyb@server:~/dir_test/src$ nm libmycal.a 			# 查看静态库包含哪些函数

add.o:
0000000000000000 T add

div.o:
0000000000000000 T div

mul.o:
0000000000000000 T mul

sub.o:
0000000000000000 T sub
zyb@server:~/dir_test/src$ mv libmycal.a ../lib/
zyb@server:~/dir_test/src$ cd ..
zyb@server:~/dir_test$ gcc main.c -I ./include/ -L ./lib/ -l mycal -o app
zyb@server:~/dir_test$ ./app 
sum = 26
zyb@server:~/dir_test$ ldd app 
	linux-vdso.so.1 =>  (0x00007ffec51c9000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f823cff5000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f823d3bf000)
zyb@server:~/dir_test$ file app
app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=8ecc03e9d70c87449fe283e5739b1a488a4e910e, not stripped

动态库

编译时可以不用指定动态库的路径

命名规则: libXXX.so, lib和.so固定, 有时so后面数字代表版本

制作步骤:
  (1)将源文件生成.o, gcc *.c -c -fpic|fPIC
  (2)打包gcc -shared -o libXXX.so *.o

zyb@server:~/dir_test/src$ rm -rfv *.o
removed 'add.o'
removed 'div.o'
removed 'mul.o'
removed 'sub.o'
zyb@server:~/dir_test/src$ gcc *.c -c -fpic -I ../include/		# 编译
zyb@server:~/dir_test/src$ ls
add.c  add.o  div.c  div.o  mul.c  mul.o  sub.c  sub.o
zyb@server:~/dir_test/src$ gcc -shared *.o -o libmycal.so		# 打包
zyb@server:~/dir_test/src$ ls *.so
libmycal.so
zyb@server:~/dir_test/src$ rm -rfv ../lib/*
removed '../lib/libmycal.a'
zyb@server:~/dir_test/src$ mv libmycal.so ../lib/
zyb@server:~/dir_test/src$ cd ..
zyb@server:~/dir_test$ gcc main.c -I ./include/ -L ./lib/ -l mycal -o app	# 其实可以不用指定-L库的路径
zyb@server:~/dir_test$ ./app 		# 会显式动态库无法加载
./app: error while loading shared libraries: libmycal.so: cannot open shared object file: No such file or directory
zyb@server:~/dir_test$ ldd app 
	linux-vdso.so.1 =>  (0x00007ffe9d5e2000)
	libmycal.so => not found				# 显示无法找到
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8bd5432000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f8bd57fc000)
zyb@server:~/dir_test$ file app 
app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=cc443641c017d8ca53c717d925d84e9a3e3fadb4, not stripped

库的使用
(1)头文件
(2)动态库libXXX.so

动态库加载:
  拷贝制作好的动态库到/lib或/usr/lib目录中
  使用环境变量进行设置
    临时设置: export LD_LIBRARY_PATH=/path/to/library:$LD_LIBRARY_PATH
    永久设置: 分为用户级别和系统级别, 在相应文件中添加export LD_LIBRARY_PATH=/path/to/library:$LD_LIBRARY_PATH
      用户级别: ~/.bashrc 重启终端或source .bashrc
      系统基本: /etc/profile
  更新/etc/ld.so.cache文件列表
    找到一个配置文件: /etc/ld.so.conf, 把动态库的绝对路径添加到文件中
    执行命令sudo ldconfig -v
  函数调用: dlopen, dlclose, dlsym, 回调函数, 函数指针

zyb@server:~/dir_test$ gcc main.c -I ./include/ -l mycal -o app		# 没有指定库路径
zyb@server:~/dir_test$ sudo mv lib/libmycal.so /lib
[sudo] password for zyb: 
zyb@server:~/dir_test$ ./app 
sum = 26
zyb@server:~/dir_test$ echo $LD_LIBRARY_PATH

zyb@server:~/dir_test$ export LD_LIBRARY_PATH=./lib/:$LD_LIBRARY_PATH
zyb@server:~/dir_test$ echo $LD_LIBRARY_PATH
./lib/:
zyb@server:~/dir_test$ ldd app 
	linux-vdso.so.1 =>  (0x00007ffd9d2fa000)
	libmycal.so => ./lib/libmycal.so (0x00007fb16f488000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb16f0be000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fb16f68a000)
zyb@server:~/dir_test$ ./app 
sum = 26
zyb@server:~/dir_test$ export LD_LIBRARY_PATH=
zyb@server:~/dir_test$ echo $LD_LIBRARY_PATH

zyb@server:~/dir_test$ sudo vim /etc/ld.so.conf
zyb@server:~/dir_test$ fg
sudo vim /etc/ld.so.conf
zyb@server:~/dir_test$ sudo cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf

/home/zyb/dir_test/lib/
zyb@server:~/dir_test$ sudo ldconfig -v
#...
zyb@server:~/dir_test$ ./app 
sum = 26
原文地址:https://www.cnblogs.com/hesper/p/10672984.html