linux知识点——静态库、动态库
本文主要讲述, Linux 静态库、动态库概念及用法简介。
前情概要:
- 静态函数库定义、特点。
- 静态函数库创建及使用案例。
- 动态函数库定义、特点。
- 动态函数库创建及使用案例。
1.静态函数库(大、快、升级不方便,需要重新编译)
是在程序执行前就加入到目标程序中去了。静态库函数允许程序员把程序link起来而不用重新编译代码,节省了重新编译代码的时间。静态函数库对开发者来说还是很有用的,例如你想把自己提供的函数给别人使用,但是又想对函数的源代码进行保密,你就可以给别人提供一个静态函数库文件。理论上说,使用ELF格式的静态库函数生成的代码可以比使用共享函数库(或者动态函数库)的程序运行速度上快一些,大概1-5%。
静态库创建及使用:
(1)使用gcc汇编源代码,输出 “*.o” 文件
(2)使用 ar -rcs 命令生成静态库
(3)编译时,使用静态库
如有: main.c show.c show.h 三个文件,main.c中使用了show.c中的函数,则有:
- 使用gcc汇编源代码,输出 “*.o” 文件
gcc -o show.o -c show.c
==》
输出文件:show.o
- 使用 ar -rcs 命令生成静态库
ar -rcs libshow.a show.o
==》
输出文件:libshow.a
- 编译使用静态库,main.c 中务必要 #include “show.h”,则有两种命令格式:
gcc -o main main.c -L ./ -lshow
或者 gcc -o main main.c libshow.a
==》
均可输出可执行文件:main
注1:-L ./ 为指定 静态库所在路径 ;
注2:-l + libname 连在一起,为固定格式,不需要加 “lib” 前缀。
注3*:使用 -l 选项时,-o选项的目的名要在-l链接的库名之前,否则gcc会认为-l是生成的目标而出错。
ar : archivefile objfile
archivefile:archivefile是静态库的名称
objfile:objfile是已 .o 为扩展名的中间目标文件名,可以多个并列
参数 意义
-r 将objfile文件插入静态库尾或者替换静态库中同名文件
-x 从静态库文件中抽取文件objfile
-t 打印静态库的成员文件列表
-d 从静态库中删除文件objfile
-s 重置静态库文件索引
-v 创建文件冗余信息
-c 创建静态库文件
2.动态函数库/共享函数库(小、慢、升级方便)
动态函数库与共享函数库是一个东西(在linux上叫共享对象库, 文件后缀是.so ,windows上叫动态加载函数库, 文件后缀是.dll),在编译的时候并没有被编译进目标代码中,程序执行到相关函数时才调用该函数库里的相应函数。
共享函数库中的函数是在当一个可执行程序在启动的时候被加载。如果一个共享函数库正常安装,所有的程序在重新运行的时候都可以自动加载最新的函数库中的函数。对于Linux系统还有更多可以实现的功能:
1、升级了函数库但是仍然允许程序使用老版本的函数库。
2、当执行某个特定程序的时候可以覆盖某个特定的库或者库中指定的函数。
3、可以在库函数被使用的过程中修改这些函数库。
动态库创建与使用:
(1)遵循约定
1)命名规则
2)命名关系
每个共享函数库都有个特殊的名字,称作“soname”。soname名字命名必须以“lib”作为前缀,然后是函数库的名字,然后是“.so”,最后是版本号信息。不过有个特例,就是非常底层的C库函数都不是以lib开头这样命名的。
每个共享函数库都有一个真正的名字(“real name”),它是包含真正库函数代码的文件。真名有一个主版本号,和一个发行版本号。最后一个发行版本号是可选的,可以没有。主版本号和发行版本号使你可以知道你到底是安装了什么版本的库函数。另外,还有一个名字是编译器编译的时候需要的函数库的名字,这个名字就是简单的soname名字,而不包含任何版本号信息。
(2)创建动态库案例
1.建立动态库程序文件: show.c、 show.h
[show.c]
#include <stdio.h>
void show(int num)
{
printf("num is: %d\n", num);
}
[show.h]
#ifndef __SHOW_H__
#define __SHOW_H__
void show(int num);
#endif
2.创建 object 文件(注:-g -Wall参数不是必须的)
gcc -fPIC -g -c -Wall show.c
===>
输出 show.o 文件
3.生成动态库
gcc -shared -Wl,-soname,show.so.1 -o show.so.1.0.1 show.o -lc
==>
输出 show.so.1.0.1 文件
4.拷贝或建立软链接至 “/lib” 路径下
sudo ln -s /home/zhong/workspace/test/lib_test/dy_lib_test/show.so.1.0.1 /lib/show.so
*注:其中,/home/zhong/workspace/test/lib_test/dy_lib_test/ 为 show.so.1.0.1 的绝对路径,软链接建立过程中务必使用绝对路径。
5.动态库使用: 创建用户程序main.c
[main.c]
#include <stdio.h>
#include <dlfcn.h> /* 包含动态链接功能接口文件 */
#include "show.h" /* 包含用户接口文件 */
#define SOFILE "/lib/show.so" /* 指定动态链接库名称 */
int main(void)
{
int num = 3;
void *dp;
dp = dlopen(SOFILE, RTLD_LAZY); /* 打开动态链接库 */
if (dp==NULL) {
printf("show.so open err!\n");
return -1;
}
void (*show)(int) = dlsym(dp, "show");
show(num);
dlclose(dp);
return 0;
}
6.编译用户程序
gcc -o main main.c -ldl
===>
输出用户可执行程序 main
执行即可。
./main
===>
输出:
num is: 3
7.动态库的更新,假设 show.c 文件打印字符串已修改:
[show.c]
#include <stdio.h>
void show(int num)
{
printf("new! new! new! test, num is: %d\n", num);
}
只需要删除:show.so.1.0.1 文件,重新执行“2.”“3.”两个步骤即可,对于不同版本的动态库改变,可以改变软链接。
动态库更新后需要执行 “ldconfig” 命令,刷新 “/etc/ld.so.cache”,重新执行main,即发现已实现新的打印输出。
sudo ldconfig
./main
===>输出:
new! new! new! test, num is: 3