前言

静态链接库会编译进可执行文件,并被加载到内存,会造成空间浪费

静态链接库对程序的更新、部署、发布带来麻烦。如果静态库更新了,使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)

动态库在程序编译时并不会被链接到目标代码中,而是在执行文件中记录对动态库的引用,在程序运行时才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才被载入,也解决了静态库对程序的更新、部署和发布带来的麻烦,用户只需要更新动态库即可,增量更新。

Linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件。

特点

  • 动态库把对一些库函数的链接载入推迟到程序运行的时期
  • 可以实现进程之间的资源共享。(因此动态库也称为共享库)
  • 将一些程序升级变得简单。
  • 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)

生成动态链接库

  1. 编写源文件
  2. 将一个或几个源文件编译链接,生成共享库。
  3. 通过 -L<path> -lxxx 的gcc选项链接生成的libxxx.so。
  4. 把 libxxx.so 放入链接库的标准路径,或指定 LD_LIBRARY_PATH,才能运行链接了libxxx.so的程序。

例子

源文件

add.c

int add(int a, int b)
{
return a + b;
}

subtract.c

int subtract(int a, int b)
{
return a - b;
}

编译

gcc -fPIC -c add.c
gcc -fPIC -c subtract.c

其中,PIC是 Position Independent Code 的缩写,表示要生成位置无关的代码,这是动态库需要的特性

链接

gcc -shared -o libmymath.so subtract.o add.o

-shared是链接选项,告诉gcc生成动态库而不是可执行文件

这两步可以合并成一个命令:

gcc -o libmymath.so -fPIC -shared subtract.c add.c

编写头文件

#ifndef _MYMATH_H_
#define _MYMATH_H_ int add(int, int);
int subtract(int, int); #endif

使用链接库

main.c

#include <stdio.h>
#include "mymath.h" int main()
{
printf("%d, %d\n", add(, ), subtract(, )); return ;
}

链接

gcc main.c -L. -lmymath

如果同一目录下同时存在同名的动态库和静态库,比如 libmymath.so 和 libmymath.a 都在当前路径下,则gcc会优先链接动态库。

运行

当执行 ./a.out,发现程序报错

./a.out: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory

这涉及到程序如何定位共享库文件

  1. 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)
  2. 对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段 -- 环境变量LD_LIBRARY_PATH -- /etc/ld.so.cache文件列表 -- /lib/,/usr/lib 目录找到库文件后将其载入内存。

/etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件生成的

所以,我们想让程序找到自己写的动态链接库,有如下方法:

  • 指定 LD_LIBRARY_PATH 环境变量为 libmymath.so 文件所在的目录
  • 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径; 同时,运行ldconfig ,该命令会重建/etc/ld.so.cache文件
  • 把 libmymath.so 拷贝到/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作

我们可以执行:

LD_LIBRARY_PATH=. ./a.out

Makefile

.PHONY: all

all: build target

build: libmymath.so
libmymath.so: add.o subtract.o
gcc -o $@ -shared $^
add.o: add.c
gcc -c -fPIC $<
subtract.o: subtract.c
gcc -c -fPIC $< target: a.out
a.out: main.c
gcc main.c -L. -lmymath .PHONY: clean
clean:
rm *.o a.out libmymath.so

linux动态链接库的更多相关文章

  1. Linux动态链接库的创建与使用

    Linux动态链接库的创建与使用1. 介绍     使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数 ...

  2. linux 动态链接库查找方法;查找动态链接库位置; LIBRARY_PATH 和 LD_LIBRARY_PATH 的区别;LD_LIBRARY_PATH and LD_RUN_PATH的区别;

    今天配置之前项目的时候,发现有些动态链接库变了,想看看现在应用在使用哪些动态链接库的时候,进一步查了点资料: 下面针对linux动态链接库查找方法和动态链接库位置配置的过程进行记录: LIBRARY_ ...

  3. Linux 动态链接库

    如何使用动态链接库 Linux下打开使用动态链接库需要三步(实际上和windows下基本一样):1.加载动态链接库,通过调用库函数dlopen()获得链接库的句柄,对应于windows下的 AfxLo ...

  4. Linux 动态链接库学习笔记

    参考资料: http://www.linuxidc.com/Linux/2012-01/50739.htm http://www.yolinux.com/TUTORIALS/LibraryArchiv ...

  5. linux动态链接库---一篇讲尽

    一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误, 比如: tmux: error while loading shared libraries: libevent-1.4.s ...

  6. Linux动态链接库的生成和使用

    目录 1. 编写C程序 2. 编译动态链接库 3. 使用共享库 4. 执行程序 5. 参考资料 1. 编写C程序 比如编写myfunc.c文件,里面包含两个函数,一个是say_hello,另一个是ca ...

  7. Linux 动态链接库 - dll劫持

    如何使用动态链接库 Linux下打开使用动态链接库需要三步(实际上和windows下基本一样):1.加载动态链接库,通过调用库函数dlopen()获得链接库的句柄,对应于windows下的 AfxLo ...

  8. Linux 动态链接库(.so)的使用

    1. 背景 库:就是已经编写好的,后续可以直接使用的代码. c++静态库:会合入到最终生成的程序,使得结果文件比较大.优点是不再有任何依赖. c++动态库:动态库,一个文件可以多个代码同时使用内存中只 ...

  9. Linux动态链接库的使用

    1.前言 在实际开发过程中,各个模块之间会涉及到一些通用的功能,比如读写文件,查找.排序.为了减少代码的冗余,提高代码的质量,可以将这些通用的部分提取出来,做出公共的模块库.通过动态链接库可以实现多个 ...

随机推荐

  1. jave web 监听器。

    https://www.imooc.com/video/5664 Web监听器由Servlet规范提供的,可以监听客户端的请求以及服务端的操作,即监听ServletContext.HttpSessio ...

  2. July 18th 2017 Week 29th Tuesday

    My heart is stronger now that you are in it. 我的心里有了你,从此变得更强大. You will no longer feel lonely if ther ...

  3. 三、基于任务的异步模式(TAP),推荐使用

    一.引言 在上两个专题中我为大家介绍.NET 1.0中的APM和.NET 2.0中的EAP,在使用前面两种模式进行异步编程的时候,大家多多少少肯定会感觉到实现起来比较麻烦, 首先我个人觉得,当使用AP ...

  4. php生成csv文件并提供下载及相关注意事项

    1.生成文件过程略,只要逗号分割就可以了 2.提供下载加上如下代码: header("Content-type: application/octet-stream"); heade ...

  5. 解析csv数据导入mysql的方法

    mysql自己有个csv引擎,可以通过这个引擎来实现将csv中的数据导入到mysql数据库中,并且速度比通过php或是python写的批处理程序快的多. 具体的实现代码示例: 代码如下: load d ...

  6. VB.NET & DataGridView与数据库的连接

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/huo065000/article/details/37378313      加入删除用户,这就又要 ...

  7. HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/500 ...

  8. wampserver 最新版本 mysql修改数据库密码

    由于wampsever版本更新就导致以前版本的密码修改造成失败,主要是密码字段改变造成的! 第一步 进入MySQL 控制台  wamp安装,数据库是没有密码 进入控制台直接回车就可以了 第二步 使用 ...

  9. 4springboot:日志(下)

    1.指定配置  位置: 给类路径下放上每个日志框架自己的配置文件即可: SpringBoot就不使用他默认配置的了 使用什么日志则配置什么文件以及注意文件名 自定义: <?xml version ...

  10. shiro认证策略,授权

    有具体问题的可以参考之前的关于shiro的博文,关于shiro的博文均是一次工程的内容 ! 认证策略: 修改认证策略: applicationContext.xml <!-- 认证器 --> ...