• 动态链接库一般不开放源码,需要建工程才能使用(其中提供的接口和 API);

0. .a/.o/.so

What are .a and .so files?

  • .o 就相当于 windows 里的 obj 文件 ,一个 .c 或 .cpp 文件对应一个 .o 文件
  • .a 是多个 .o 合在一起,用于静态连接 ,即STATIC mode,多个.a可以链接生成一个exe的可执行文件
    • -a:archive libraries,
  • .so 是 shared object ,用于动态连接的,和windows的dll差不多,运行时才载入。
  • .a 与 .so 的区别也就是静态链接和动态链接的区别,
    • 静态链接库(编译期链接),当库的内容发生变化时,需要重新编译代码;

      • gcc -c
    • 动态链接库(运行期链接),也即在 gcc -o 生成 .o 文件之后,

1. 静态库与动态库

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

  • 静态库(static libaray),通常文件名为“libxxx.a”的形式,库函数编译期链接

其实,我们也可以把对一些库函数的链接载入推迟到程序运行时期(runtime)。这就是如雷贯耳的动态链接库(dynamic link library)技术。动态链接库的名字形式为 “libxxx.so” 后缀名为 “.so”

  • 动态库(dynamic link library),后缀为”.so”,运行时链接

2. 静态链接库、动态链接库各自的特点

  1. 动态链接库有利于进程间资源共享

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

  2. 将一些程序升级变得简单。用静态库,如果库发生变化,使用库的程序要重新编译。使用动态库,只要动态库提供给该程序的接口没变,只要重新用新生成的动态库替换原来就可以了。

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

  4. 由于静态库在编译的时候,就将库函数装载到程序中去了,而动态库函数必须在运行的时候才装载,所以程序执行的时候,用静态库更快些

3. 静态库、动态库的创建

无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序通过gcc先编译成.o文件。

3.1 静态库:

gcc –c file1.c file2.c
ar cr libxxx.a file1.o file2.o

3.2 动态库

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

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

4. 静态库和动态库的使用

两者的使用相同:

gcc –o main main.o libxxx.a(libxxx.so)

或者为:

gcc –o main main.o –L. –lxxxx

gcc file1.o file2.o -Lpath -lxxx -o program
编译器会先到path目录下搜索libxxx.so文件,如果没有找到,继续搜索libxxx.a(静态库)。

在程序运行期间,也需要告诉系统去哪里找你的动态链接库文件。在UNIX下是通过定义名为 LD_LIBRARY_PATH 的环境变量来实现的。只需将 path 赋值给此变量即可。csh 命令为:
setenv LD_LIBRARY_PATH your/full/path/to/dll
一切安排妥当后,你可以用 ldd 命令检查是否连接正常。
ldd program //可以看到它是如何调用动态库中的函数的。

编译参数解析:

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

  • -Lpath:表示在path目录中搜索库文件,如-L.则表示在当前目录。

  • -Ipaht:表示在path目录中搜索头文件。

  • -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加lib,后面加上.so来确定库的名称lLD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。

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

注意:

调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过

“-I “include进来了,库所在目录通过 “-L”参数引导,并指定了”-l”的库名,但通过 ldd 命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf 文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。特别注意在使用交叉编译器编译了一个程序后,当移植到ARM平台运行时,由于往往采用的是动态链接库,在ARM平台发现报错,说找不到文件,其实是因为程序所依赖的动态库函数在ARM平台的linux下没有,往往解决的办法有两个:

  • 在PC机,编译时才有静态编译,即加-static

  • 将相应的动态库文件同程序一起移植到ARM平台的 linux 中,并且要保证目录。

参考

  1. Linux应用编程之静态链接库和动态链接库

UNIX环境高级编程(三)—— 静态链接库与动态链接库相关推荐

  1. Linux环境下c语言静态链接库和动态链接库创建和使用

    库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀. 面对比一下两者: 静态链接库:当要使用时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功, ...

  2. UNIX环境高级编程--标准I/O库(二)

        在文件I/O中所有函数都是针对文件描述符的,对于标致I/O库,他们的操作则是围绕流进行的.当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件相关联.     当打开一个流时,标准I ...

  3. 《UNIX 环境高级编程》学习笔记—— 标准I/O库

    UNIX环境高级编程--标准I/O库 流和 FILE 对象 标准输入.标准输出和标准错误 缓冲 打开流 读和写流 每次一行 I/O 二进制 I/O 定位流 格式化 I/O 临时文件 内存流 流和 FI ...

  4. UNIX环境高级编程(第三版 源码及编译好的静态库文件)

    UNIX环境高级编程(第三版) 源码 及 库文件 链接: https://pan.baidu.com/s/1tPY17lWNDEbzkOwZaRUUNg 提取码: 1024 复制这段内容后打开百度网盘 ...

  5. UNIX环境高级编程(第三版)关于apue.h的用法

    UNIX环境高级编程(第三版)中的例子用到apue.h这个头文件,但是书里面写的地址已经不能访问. 经过一番查找之后,找到如下解决方案: 1.到www.apuebook.com上下载第2版的源码,也可 ...

  6. UNIX环境高级编程-第三版

    Unix环境高级编程-第三版 之前学习了<Linux系统编程>对于常见的概念和函数都有了基础的认知,这里准备通过这本书,深入学习系统API相关内容.笔记内容会有所倾向,不会严格反应书本内容 ...

  7. (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  8. Linux - Unix环境高级编程(第三版) 代码编译

    Unix环境高级编程(第三版) 代码编译 本文地址:http://blog.csdn.net/caroline_wendy 时间:2014.10.2 1. 下载代码:http://www.apuebo ...

  9. Unix环境高级编程 笔记

    Unix环境高级编程(第二版)学习笔记 这是一次较长时间的整理,然而跳跃了一些章节和很多知识点,仍然是很不完善很不全面的. 前言 操作系统某些问题 严格意义上,可将操作系统定义为一种软件,它控制计算机 ...

最新文章

  1. 微信小程序获取手机系统信息
  2. pandas.core.frame.DataFrame是什么数据结构,为什么要如此取值  [ ]中嵌套[ ]
  3. Xamarin 2017.9.13发布更新
  4. ADT更新过慢与更新Android SDK过慢
  5. mui 头部tab代码
  6. vmware下Ubuntu屏幕分辨率设置
  7. Could not obtain transaction-synchronized Session for current thread原因及解决方案
  8. Jquery easyui 密码两次输入相等的验证
  9. 智能手机或许非诺基亚最佳战场,功能手机才是出路?
  10. ffmpeg 简单教程
  11. java udp发16进制数据_如何通过接口强制发送UDP数据包?
  12. caffe框架的介绍
  13. 浏览器阻挡cookies_如何在任何浏览器中阻止Cookies(除了您使用的网站外) | MOS86...
  14. C语言——单词精确查找
  15. ps3自制linux,下BT聊QQ !PS3安装Linux ubuntu 7.10详细图文教程
  16. exchange服务器重装后,exchange服务器之exchange 2016卸载及重装的经历
  17. android 判断是否安装百度地图,判断手机是否安装高德/百度地图
  18. CorelDRAW X8 /CDR2020官方序列号密钥下载矢量绘图软件
  19. Windows Server 2012 之NIC组合(NIC Teaming)介绍
  20. 今天我们谈谈关于java自学的那些事儿(为那些目标模糊的码农们)

热门文章

  1. php黑名单绕过,利用最新Apache解析漏洞(CVE-2017-15715)绕过上传黑名单
  2. Doris 之Frontend(FE)和Backend(BE)配置
  3. 计算机系统访问控制的功能,访问控制是为了限制访问主体对访问客体的访问权限,从而使计算机系统在合法范围内使用的安全措施,以下关于访问控制的叙述中,()是不正确的 - 信管网...
  4. scala从url或者其他数据源读取数据
  5. 南宁二中三中高考2021成绩查询,2020年南宁二中三中录取总成绩不低于A
  6. Numpy——numpy的基本运算
  7. Python模块——matplotlib模块详解
  8. oracle有三种类型的异常错误: 预定义 ( Predefined )错误里面的常见错误
  9. 牛客网 斐波那契数列
  10. 创建私有 Gems 源