这篇文章对于动态库的概念及使用介绍的很不错,故收藏了。
一、引言

通常情况下,对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下。所以这些函数库被成为静态库(static libaray),通常文件名为“libxxx.a”的形式。

其实,我们也可以把对一些库函数的链接载入推迟到程序运行的时期(runtime)。这就是如雷贯耳的动态链接库(dynamic link library)技术。

二、动态链接库的特点与优势

首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:

1. 可以实现进程之间的资源共享。

什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。

2. 将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。

3. 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。

程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。

三、动态链接库的创建

由于动态链接库函数的共享特性,它们不会被拷贝到可执行文件中。在编译的时候,编译器只会做一些函数名之类的检查。在程序运行的时候,被调用的动态链接库 函数被安置在内存的某个地方,所有调用它的程序将指向这个代码段。因此,这些代码必须实用相对地址,而不是绝对地址。在编译的时候,我们需要告诉编译器, 这些对象文件是用来做动态链接库的,所以要用地址不无关代码(Position Independent Code (PIC))。

对gcc编译器,只需添加上 -fPIC 标签,如:

gcc -fPIC -c file1.c
gcc -fPIC -c file2.c
gcc -shared libxxx.so file1.o file2.o

注意到最后一行,-shared 标签告诉编译器这是要建立动态链接库。这与静态链接库的建立很不一样,后者用的是 ar 命令。也注意到,动态链接库的名字形式为 “libxxx.so” 后缀名为 “.so”

四、动态链接库的使用

使用动态链接库,首先需要在编译期间让编译器检查一些语法与定义。

这与静态库的实用基本一样,用的是 -Lpath 和 -lxxx 标签。如:

gcc file1.o file2.o -Lpath -lxxx -o program.exe

编译器会先在path文件夹下搜索libxxx.so文件,如果没有找到,继续搜索libxxx.a(静态库)。

在程序运行期间,也需要告诉系统去哪里找你的动态链接库文件。在UNIX下是通过定义名为 LD_LIBRARY_PATH 的环境变量来实现的。只需将path赋值给此变量即可。csh 命令为:

setenv LD_LIBRARY_PATH your/full/path/to/dll

一切安排妥当后,你可以用 ldd 命令检查是否连接正常。

ldd program.exe

动态链接库*.so的编译与使用

动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前一直不太了解得东东,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。
1、动态库的编译

下面通过一个例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。

so_test.h:void test_a();
void test_b();
void test_c();test_a.c:#include "so_test.h"void test_a()
{printf("this is in test_a...\n");
}test_b.c:#include "so_test.h"void test_b()
{printf("this is in test_b...\n");
}test_a.c:#include "so_test.h"void test_c()
{printf("this is in test_c...\n");
}

将这几个文件编译成一个动态库:libtest.so
gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so

2、动态库的链接

在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c。

test.c:#include "so_test.h"int main()
{test_a();test_b(); test_c();return 0;
}

将test.c与动态库libtest.so链接生成执行文件test:

gcc test.c -L. -ltest -o test

测试是否动态连接,如果列出libtest.so,那么应该是连接正常了

ldd test

l 执行test,可以看到它是如何调用动态库中的函数的。
3、编译参数解析
最主要的是GCC命令行的一个选项:
-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件

-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。

-L.:表示要连接的库在当前目录中

-ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称

LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。

当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。
4、注意

调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。

【转载】linux静态链接库与动态链接库的区别及动态库的创建相关推荐

  1. python库和模块的区别_Python动态库模块的名称与文件名不同

    在Python中,模块的名称通常与相应文件的名称相同,但是我遇到了与模块无关的问题,事实并非如此: 1 2 3 4 5 6me@host:/usr/lib/python2.7/dist-package ...

  2. linux 静态链接 mysql glibc 库的悲催过程 - mango的日志 - 网易博客

    linux 静态链接 mysql glibc 库的悲催过程 - mango的日志 - 网易博客 linux 静态链接 mysql glibc 库的悲催过程 - mango的日志 - 网易博客 linu ...

  3. 【Android NDK 开发】Android Studio 使用 CMake 导入动态库 ( 构建脚本路径配置 | 指定动态库查找路径 | 链接动态库 )

    文章目录 I . CMake 引入动态库与静态库区别 II . Android Studio 中 CMake 引入动态库流程 III . 指定动态库查找路径 IV . 链接函数库 V . 完整代码示例 ...

  4. linux直接运行程序加载动态库失败,扣丁学堂Linux培训详解程序运行时加载动态库失败解决方法...

    今天扣丁学堂Linux培训老师给大家介绍一下关于Linux程序运行时加载动态库失败的解决方法,希望对同学们学习有所帮助,下面我们一起来看一下吧. Linux下不能加载动态库问题 当出现下边异常情况 . ...

  5. 如何用gcc编译器生成动态链接库*.so文件(动态库)

    如何用gcc编译器生成动态链接库*.so文件(动态库) 当源文件为string.c时,生成动态链接库,假设名称为libstr.so 生成动态链接库的命令行为: gcc -fPIC -shared -o ...

  6. qt生成无ui界面动态库,有ui界面的动态库,以及含有资源文件和qss文件的动态库

    提要 此文分别就qt生成纯代码的动态库,含有ui文件的动态库以及含有资源文件qss文件和切图的动态库. 实现 1.纯代码的生成qt库.即没有ui文件的项目. 打开QtCreate,新建文件,选择lib ...

  7. Linux 静态链接库与动态链接库之一:静态链接库生成及使用

    (1)引言       通常情况下,对函数库的链接是放在编译时期(compile time)完成的.所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文 ...

  8. libcurl linux 静态链接库_GCC 程序编译的静态链接和动态链接

    转自:Mr_Bluyee 在链接阶段中,所有对应于源文件的 .o 文件."-l" 选项指定的库文件.无法识别的文件名(包括指定的.o目标文件和.a库文件)按命令行中的顺序传递给链接 ...

  9. libcurl linux 静态链接库_Linux ubuntu OpenSSL + curl 静态库编译及使用

    下载源码 源码编译 解压之后,进入源码目录openssl-1.1.0f,执行如下命令.因为只需要编译静态库,也没有特殊要求,所以使用的编译选项配置很简单: ./config -fPIC no-shar ...

最新文章

  1. 第一个 mac 程序 Create-JSON-Model
  2. 【Canvas】如何用Canvas绘制折线图
  3. 在Cocos2d中实现能够惯性拖动的选择界面
  4. iOS:图片上传时两种图片压缩方式的比较
  5. 用c语言编写一个2048 游戏,求c语言编写的2048游戏代码,尽量功能完善一些
  6. python列表生成器语法_python列表生产式和生成器
  7. bootstrap confirm 确认后在执行_如何利用 Laravel 提供的密码确认功能来保护用户信息安全...
  8. Lecture 3:动态规划
  9. Norton Internet Security 序列号提取(卡饭)
  10. Remoting整理
  11. 软件工程专业学习路线
  12. vs2019下载安装
  13. 深度学习笔记(二十)Momentum动量梯度下降及RSMprop Adam优化算法
  14. 当今社会到底更需要专才还是通才
  15. Ping IPv6在线测试检测 testipv6 加速镜像
  16. 国际清算银行成员发布央行数字货币分析报告
  17. (已修正精度 1mm左右)Realsense d435i深度相机+Aruco+棋盘格+OpenCV手眼标定全过程记录
  18. [82]redis中如何切换db
  19. nrf51822 --TWI(硬件IIC)
  20. 超大Excel读取和写出(支持50万+)(一)

热门文章

  1. Linux那些事儿之我是Sysfs(7)dentry与inode
  2. 4.1 ucGUI 图片显示方法
  3. sqlserver mysql 乱码_SQLServer数据库如何解决中文乱码问题?方法有哪些?
  4. node 获取表单数据 为空_数据结构与算法(python)单向循环链表
  5. Ubuntu 14.04 64位字体美化(使用文泉驿微黑)
  6. 深入理解ceph-disk prepare 源码逻辑
  7. 自己开发开源jquery插件--给jquery.treeview加上checkbox
  8. [冲昏头脑]IDEA中的maven项目中学习log4j的日志操作
  9. 数据库原理与设计 P75作业 学号2013211466 班级0401302
  10. ios 如何改变UISegmentedControl文本的字体大小?