在嵌入式开发中,"库"是我们非常熟悉的一个词,在针对Linux这边目标平台进行开发时,静态库和动态库都会涉及到。而对目标平台为RTOS这类小系统时,常用到的静态库的方式

基本概念,什么是库?

静态库

静态库和动态库是不同的,静态库是不涉及到符号重定位之类的问题。静态库本质上只是将一堆目标文件进行打包.
静态库的代码在编译过程中已经被载入可执行程序中,因此最终生成的可执行程序体积相对较大些.

静态库命名规则,
lib开头, .a 为后缀, 例如sayhello静态库 -> libsayhello.a

动态库

动态库的代码是在可执行程序运行时才加载到内存中的,在编译链接过程只是简单的引用,因此生成的可执行程序相对较小.
相对于静态库,除了可执行程序体积小外,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该动态库的实例,另外当只是修改动态库的内容时,不需要重新编译可执行程序.

动态库命名规则,
lib开头,.so为后缀 例如sayhello动态库 -> libsayhello.so

补充说明: 为了在同一系统中能够使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libsayhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。

 ln -s libsayhello.so.1.0 libhello.so.1ln -s libhello.so.1.0 l ibhello.so

如何生成静态库 & 动态库

静态库的生成

以下面代码为例,生成sayhello的.a库 - libsayhello.a

/* file: sayhello.c */#include <stdio.h>void test();void sayhello()
{printf("Say Hello \r\n");
}

在这里以及接下来的文章都是基于gcc进行处理的.

  1. 使用gcc命令以及-c参数生成目标文件sayhello.o
gcc -c sayhello.c -o sayhello.o
  1. 使用ar命令以及cqs参数生成静态库 libsayhello.a
ar cqs libsayhello.a sayhello.o

补充说明: 在sayhello.c 中test函数,只是声明未定义,但这样在生成目标文件和静态库是不会报错的,但在链接成可执行程序时会报该函数未定义的编译错误. 这一点后面会做补充说明.

动态库的生成

基于上面的.o 文件 - sayhello.o 进行(无论时静态库还是动态库,在生成目标文件这一过程时相同的)
生成动态库,

gcc -fPIC -shared libsayhello.so hello

补充说明,
-shared: 该选项指定生成动态连接库
-fPIC:表示编译为位置独立(地址无关)的代码,不用此选项的话,编译后的代码是位置相关的,所以动态载入时,是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的.

相关工具的使用

ldd

使用ldd工具查看可执行程序或者动态库依赖于哪些动态库.

nm

使用nm工具查看静态库或者动态库中有哪些函数名
nm工具可以打印出库中的涉及到的所有符号,这里的库既可以是静态的也可以是动态的.

nm列出的符号常见有如下三种:

  • T类,是在库中定义的函数,用T表示,这是最常见的
  • U类,是在库中被调用的,但并没有在库中定义
  • W类,是所谓的“弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示.
ar

可以通过ar指令来查看,静态库中包含哪些 .o 文件,即是由哪些源文件编译汇编而来.

objdump

需要额外补充


库的依赖问题

例如我们有一个基础库libbase.a, 还有一个依赖libbase.a的库-> libsayhello.a, 那么我们需要注意在编译时一定需要先-lsayhello 在-lbase. 如果使用-lbase 再-lsayhello 则编译会报错,会出现一些函数未定义.

为什么会有库的依赖问题
  1. 静态库解析符号引用
    这里涉及到的时链接器ld是如何使用静态库来解析引用的. 在符号链接阶段,ld从左到右依次扫描可重定位目标我呢见(.o)和静态库(.a). 在这个过程中,链接器将维持三个集合:
    1) 集合E, 可重定位目标文件(*.o文件)的集合
    2) 集合U, 未解析(未定义)的符号集,即符号表中UNDEF的符号
    3) 集合D, 已定义的符号集

    初始情况下,E、U、D都是为空.
    处理过程如下:
    1、对于每个输入文件f,如果是目标文件(.o),则将f中的符号加入E,并用f中的符号表修改U, D(在文件f中定义实现的符号是D,在f中引用的符号是U),然后继续处理下一个文件.

    2、 对于输入文件是一个静态库(*.a), 那么ld将尝试匹配U中为解析符号于静态库成员(静态库的成员就是 .o 文件)定义的符号. 如果静态库中某一个成员m(某个.o文件)定义了一个符号来解析U中的引用,那么将m加入E中. 同时使用m的符号表来更新U, D. 对静态库中所有成员目标文件反复进行该过程,直至U和D不再发生变化. 此时,静态库f中任何不包含在E中的成员目标文件都将丢弃,链接器将继续下一个文件.

    3、 当所有输入文件都完成后,如果U非空,则ld会报错,否则合并和重定位E中目标文件,构建出可执行程序

    ---- 这里需要补充流程图进行说明
    
静态库、动态库链接原理

参考链接:
https://cloud.tencent.com/developer/article/1343895
https://blog.csdn.net/shenhuxi_yu/article/details/71437167
http://www.cppblog.com/kevinlynx/archive/2014/09/15/208320.html

【C C++】静态库和动态库相关推荐

  1. 关于Linux静态库和动态库的分析

    From: http://hi.baidu.com/bdccutysj/blog/item/5bae7f0202abac7c3912bb15.html 1.什么是库 在windows平台和linux平 ...

  2. C/C++ 静态库和动态库的区别

    可执行目标文件 可重定位目标文件 共享目标文件 静态库和动态库的区别: 生效阶段不同,静态库是在编译阶段就会把其链接到可执行目标文件中:动态库是在程序运行过程中指定路径或者系统动态库路径下寻找. -l ...

  3. 静态库与动态库详细剖析

    技术交流QQ群:1027579432,欢迎你的加入! 1.库的介绍 库是什么? 二进制文件: 将源代码(.c或.cpp文件)变成二进制格式的源代码: 加密操作(只能使用,无法知道源代码是什么): 库制 ...

  4. linux 中如何将文件粘贴到usr下的lib内,学会在Linux下GCC生成和使用静态库和动态库...

    一.基本概念1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主 ...

  5. C 语言编程 — 静态库、动态库和共享库

    目录 文章目录 目录 文章目录 程序函数库 静态链接 创建静态库文件 动态链接 创建共享库文件 共享库文件的名字 共享库文件的存储路径 LD_LIBRARY_PATH 环境变量 ldconfig 指令 ...

  6. NDK 编译和使用静态库、动态库

    NDK 编译和使用静态库.动态库 情况一:编译静态库 情况二:编译动态库 情况三:编译动态库+静态库 情况四:已有第三方静态库(动态库),编译静态库(动态库) 默认所有代码和文件在$project/j ...

  7. Linux中gcc的编译、静态库和动态库的制作

    欢迎大家关注笔者,你的关注是我持续更博的最大动力 Linux中gcc的编译.静态库.动态库 文章目录: 1 gcc的编译过程 1.1 gcc的编译过程 1.2 gcc的常用参数 2 gcc 静态库的制 ...

  8. Head First C 第八章 静态库与动态库 创建动态库

    2019独角兽企业重金招聘Python工程师标准>>> Head First C 第八章 静态库与动态库 创建动态库 动态库是什么 静态库文件,需要在链接过程中和主程序链接在一起,如 ...

  9. Linux下的静态库、动态库和动态加载库

    from: http://www.techug.com/linux-static-lib-dynamic-lib 库的存在极大的提高了C/C++程序的复用性,但是库对于初学者来说有些难以驾驭,本文从L ...

  10. 【Android NDK 开发】Android.mk 配置静态库 ( Android Studio 配置静态库 | 配置动态库与静态库区别 | 动态库与静态库打包对比 )

    文章目录 I . Android Studio 中使用 Android.mk 配置静态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

最新文章

  1. K8s中的external-traffic-policy是什么?
  2. CUDA入门需要知道的东西
  3. C++二维数组动态申请内存
  4. SDK 和 API
  5. 信息学奥赛一本通(2030:【例4.16】找素数)
  6. 视觉SLAM笔记(48) 局部地图
  7. 字典的定义、字典的特性(成员操作符)
  8. java 创建Reader_java – 最佳实践:为XMLReader创建SAX解析器
  9. 直方图均衡化的代码解析
  10. 查找某个数据,找到后把符合条件数据的一行复制到另外一个地方
  11. uoj#422. 【集训队作业2018】小Z的礼物(MIn-Max容斥+插头dp)
  12. 使用jvisualvm通过JMX的方式监控远程JVM运行状况
  13. 「需求广场」需求词更新明细(三)
  14. dep指定版本 go_Golang官方依赖管理工具:dep
  15. 深度学习中Batch size对训练效果的影响
  16. java面向对象基础
  17. 刚刚,2019年中国信息通信服务交流研讨会盛大召开!
  18. IDEA使用copyright
  19. 车企们的第一辆车是什么样的
  20. 支付宝内部功能调用APPid列表

热门文章

  1. 第一篇——关于99乘法表
  2. 如何将m4v转换成mp4
  3. Python第四周作业之选择题
  4. Chromium内核浏览器编译记(一)踩坑实录
  5. 腾讯的另一面:开放连接下的可持续社会价值创新践行者
  6. 硬核!BUILD with Chainlink主题校园行技术分享会——浙大站
  7. jmu–python–判断闰年_csf
  8. 基于Qt QPainter自绘扇形统计图
  9. popstate_移动端popstate的怪异行为
  10. Eclipse安装Git插件以及通过Git导入华为软件开发云项目