动态库与静态库 动态链接与静态链接

1.动态库:库文件,以.so为后缀(Windows中为.dll)
静态库:库文件,以.a为后缀(Windows中为.lib)
库的命名规则:lib库名.后缀
见到一个库,掐头去尾才是它的库名。使用gcc进行编译的时候,默认是采用的动态链接,如果要使用静态链接需要加上选项-static。

2.动态链接:
在处理这个程序的时候,我们自己的内容正常执行
当执行到库函数的时候由运行时的链接文件跳转到系统中的标准库中,去链接标准库中库函数的.o文件
当链接完成后就生成可执行程序。
动态链接的动态就体现在,用到的库函数需要跳转到动态库中去链接对应的.o文件。
其中发生动态链接的标准库就叫做动态库。

3.静态链接:
静态库与动态库相反,它不发生跳转。
自己的程序内容正常执行,当执行到库函数的时候,会将标准库中对应的库函数内容全部复制到程序中库函数的地方。
之后再生成可执行文件。

4.静态链接和动态链接的区别:
文件特性:(静态链接)生成一个包含所有代码和数据的独立可执行文件,无需依赖外部库文件
(动态链接)生成一个相对较小的可执行文件,仅包含对外部函数/符号的引用
运行效果:(静态链接)程序运行时不需要外部共享库的支持
(动态链接)程序运行时需要依赖正确版本的外部库
动态库也叫运行时库,是运行时加载的库,将库中数据加载到内存中后,每个使用了动态库的程序都要根据加载的起始位置计算内部函数以及变量地址,因此动态链接动态库加载及运行速度相较静态链接是较为不如的,但是它也有好处,就是多个程序在内存中只需要加载一份动态库就可以共享使用。
静态链接,链接静态库,每个程序将自己在库中用到的指令代码单独写入自己可执行程序中,程序运行时无依赖,加载运行速度快,但是程序运行后有可能会有冗余代码在内存中

动态链接链接的是动态库,而动态库中包含了大量的常用的功能接口指令代码
这种链接方式,是用于解决静态库存在的浪费内存和磁盘空间,以及模块更新困难等问题。
动态链接生成可执行程序,可执行程序中会记录自己依赖的库列表以及库中的函数地址信息,等到运行程序的时候,由操作系统将库加载到内存中(多个程序可以共享,不需要加载多份相同实例),然后根据库加载后的地址在对每个程序内部用到的库函数的地址进行偏移计算
基于这么一种思想,动态链接具有以下优缺点:
<1>更加节省内存并减少页面交换;
<2>库文件与程序文件独立,只要输出接口不变,更换库文件不会对程序文件造成任何影响,因而极大地提高了可维护性和可扩展性;
<3>不同编程语言编写的程序只要按照函数调用约定就可以调用同一个库函数;
<4>适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。
<5>运行时依赖,否则找不到库文件就会运行失败
<6>运行加载速度相较静态库慢一些 需要对库版本之间的兼容性做出更多处理

(静态库,本质就是将库中的源代码直接翻译成.o目标文件)

    指令:ar -rc libname.a [所有待打包.o]
    作用:将所有待打包的.o文件制作成静态库。

该指令中,ar是gnu的归档工具(Archive files),rc表示replace和create

    指令:ar -tv 库文件名
    功能:列出静态库中的文件和详细信息。

gcc -TestMain.c -I(大写i) mymatch_lib/include -lmymath -L mymath_lib/lib
-I(大写i) 指定头文件路径
-L 指定库文件路径
-l(小写L) 指定库(掐头去尾后的库名)

Makefile 文件
5.制作静态库

static-lib=libmymath.a
$(static-lib):Add.o Div.o Mul.o Sub.o
ar -rc $@ $^ 
%.o:%.c
 gcc -c $
.PHONY:output
output:
    mkdir -p mymath_lib/include    //-p递归创建目录(如果没有父目录就创建父目录)mymath_lib/include
    mkdir -p mymath_lib/lib
    cp -f *._h mymath_lib/include  //将所有以.h结尾的文件复制到mymath_lib/include 目录中。
    cp -f *._a mymath_lib/lib      //将所有以.a结尾的文件复制到mymath_lib/lib目录中。 
.PHONY:clean
clean  rm -f *.o *.a  mymath_lib 

制作动态库

dy-lib=libmymath.so
$(dy-lib):Add.o Div.o Mul.o Sub.o
gcc -shared -o $@ $^
%.o:%.c
gcc -fpIC -c $<
.PHONY:output
output:
mkdir -p mymath_lib/include    
mkdir -p mymath_lib/lib 
cp -f *._h mymath_lib/include   
cp -f *_a mymath_lib/lib       
.PHONY:clean
clean rm -f *.o *.a mymath_lib

gcc -TestMain.c -I(大写i) mymatch_lib/include -lmymath -L mymath_lib/lib
-I(大写i) 指定头文件路径
-L 指定库文件路径
-l(小写L) 指定库(掐头去尾后的库名)

动态链接使用同样的方法不可(因为库和程序要同时被系统找到才可以)
error while loading shared libraries: libmymath.so: cannot open shared object file:No such file or directory

静态链接:将用到的库函数在编译的时候赋值到了源码中,所以编译成功就可以执行。
动态链接:在编译的时候,只是将库的位置无关码(地址偏移量)复制到了源码中,等在运行可执行程序的时候再去动态库中根据偏移量找到应用的库函数。

接下来的任务就是告诉操作系统我的动态库在哪里。

①.将库文件直接安装到系统中
sudo cp mymath_lib/include/*.h /usr/include/
(系统中的C标准库名为:libc.so,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找.)
②.通过使用软链接,查找动态库
ln -s
建目标是文件的符号链接 ln -s+<源文件路径>+<链接文件路径>
(ln -s/home/user/file.txt /home/user/link.txt,这个命令会在/home/user目录下创建一个名为link.txt的符号链接文件,指向/home/user/file.txt文件
sudo ln -s ~/test/mymath-lib/lib/libmymath.so /lib64/libmymath.so)
③. LD-LIBRARY-PATH使用环境变量的方式,让系统找到自己的动态库
在执行程序的时候,操作系统会从环境变量LD_LIBRARY_PATH中读取动态库的路径。
将自己的动态库路径放入到环境变量中,再执行刚刚生成的可执行程序,发现可以成功执行了,而且使用的是动态库中的函数接口。
这种做法并不能永久生效,因为每次启动shell的时候,它都会从配置文件中重新加载环境变量,我们这里给LD_LIBRARY_PATH赋值只是暂时的。
LD-LIBRARY-PATH=$LD-LIBRARY-PATH:/home/test/mymath-lib/lib/libmymath.so

④.直接更改系统配置文件
/etc/ld.so.conf.d/
6.静态库与动态库的加载
静态库实际上不存在加载问题,静态库如何加载就是可执行程序如何加载

  • 26
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值