当前位置: 首页 > news >正文

Linux静态库和动态链接库的制作和使用

gcc的简单介绍

预处理(cpp)
把文本文件中的预处理指令全部展开,包括头文件包含,宏替换

gcc test.c -o test.i -E

编译(ccl)
编译预处理文件,生成对应硬件平台的汇编代码

gcc test.i -o test.s -S

汇编(as)
编译汇编代码,翻译为对应处理器的二进制机器码(生成二进制文件可重定向目标文件)

gcc test.s -o test.o -c

链接库
生成可执行文件

gcc test.o -o test -lc  //链接标准的c库
gcc test.o -o test -v  //查看当前编译链接的过程


对于上述编译过程,重点关注最后一步库文件的链接(gcc test.o -o hello -lc):链接实际上是将多个.o文件合并在一起的过程。这些 *.o 文件合并前是 ELF 格式,合并后也是 ELF 格式。

ELF代表Executable and Linkable Forma,是一种对可执行文件、目标文件和库使用的文件格式,跟Windows下的PE文件格式类似。ELF格式是是UNIX系统实验室作为ABI(Application Binary Interface)而开发和发布的,早已经是Linux下的标准格式了

ELF主要包括三种类型文件:

可重定位文件(relocatable):编译器和汇编器产生的.o文件,被Linker所处理

可执行文件(executable):Linker对.o文件进行处理输出的文件,进程映像

共享对象文件(shared object):动态库文件.so

ELF格式的合并,实际上就是将多个文件中各自对应的段合并在一起,形成一个统一的ELF文件。

在此过程中,必然需要对各个 *.o 文件中的静态数据(包括常量)、函数入口的地址做统一分配和管理,这个过程就叫做 重定位,因此未经链接的单独的 *.o 文件又被称为可重定位文件,经过链接处理合并了相同的段的文件称为可执行文件。

readelf -S test.o  //显示节区表内的所有信息,包括每个节的属性readelf -h test.o  //显示在ELF文件头里包含的所有信息readelf -s test.o  //显示符号表的信息,包含静态符号表(.symtab)和动态符号表(.dynsym)


静态库和动态库

静态库在程序编译链接时,会被完整地复制到可执行文件中。
通常以.a(在 Unix/Linux 系统下)或.lib(在 Windows 系统下)为文件扩展名。它实际上是一组目标文件(.o文件)的归档集合,包含了多个函数和变量的编译后的代码。

动态库在程序运行时才被加载到内存中,供程序调用,在 Unix/Linux 系统下通常以.so为扩展名,在 Windows 系统下通常以.dll为扩展名。动态库在磁盘上是独立的文件,包含可执行代码和数据,这些代码和数据在程序运行时可以被多个程序共享。

静态库命名规范
lib库名.后缀

对于动态库而言,在后缀后面还经常会带着版本号
lib库名.后缀.版本号  


制作静态库

首先写自己的C文件,例如编写a.c和b.c包含已经封装好的函数

然后编译a.c和b.c
 

gcc a.c -o a.o -c
gcc b.c -o b.o -c

将编译完的.o文件合并为一个静态链接库

ar crs libx.a a.o b.o

查看静态链接库中的*.o文件

ar -t libx.a

删除静态链接库中的*.o文件

ar d libx.a b.o

像静态库中增加*.o文件

 ar r libx.a b.o

提取静态库中*.o文件

 ar x libx.a

提取静态库中指定*.o文件

ar x libx.a a.o

静态库的调用,在主函数调用静态库的头文件,#include “xx.h"
编译时用gcc main.c -L./ -lxx -lyy //-L./指定在当前目录下,-l指定库名

制作动态库

gcc a.c -o a.o -c -fPIC
gcc b.c -o b.o -c -fPICgcc -shared -fPIC -o libx.so a.o b.o

运行动态库

动态库的最大特征,就是编译链接后程序并不包含动态库的代码,这些程序会在每次运行时,动态地去寻找并定位其所依赖的库文件中的模块,这是他们为什么被称为动态库的原因。也就是说,如果程序运行时找不到动态库,运行就会失败

为了解决找不到动态库的问题,假设我的库路径在/home/loading/lib


有两种解决方法
1、编译时预告

gcc main.c -o main -L. -lx -Wl,-rpath=/home/loading/lib/   //-Wl选项用于将后面的参数传递给链接器

2、将动态链接库路径添加到系统变量中

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/loading/lib

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • How to stream video in a loop via RTP using ffmpeg?
  • 打造redis缓存组件
  • CAN总线/CAN应用层协议设计,理解并实践仲裁段位域定义
  • vue vite创建项目步骤
  • 推荐系统实战(四)精排-交叉结构
  • 【第55课】XSS防御HttpOnlyCSP靶场工具等
  • 如何使用ssm实现游戏攻略网站的设计与实现+vue
  • 测试员阿聪的破局之路:从迷茫到帝都站稳脚跟,大佬亲授良方
  • 想学网络,为什么要先学数通?
  • 【图机器学习系列】(二)从传统机器学习角度理解图(一)
  • 正交试验法(或PICT)来设计测试用例
  • 如何使用ssm实现在线云音乐系统的设计与实现
  • 探索提示工程 Prompt Engineering的奥妙
  • 通过 OpenAI Embedding 接口计算相似度
  • 四川财谷通,信息科技引领者!
  • 【node学习】协程
  • 【译】理解JavaScript:new 关键字
  • 〔开发系列〕一次关于小程序开发的深度总结
  • 0x05 Python数据分析,Anaconda八斩刀
  • Android 控件背景颜色处理
  • axios 和 cookie 的那些事
  • JavaScript函数式编程(一)
  • js写一个简单的选项卡
  • magento2项目上线注意事项
  • Node 版本管理
  • php的插入排序,通过双层for循环
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • 编写符合Python风格的对象
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 大主子表关联的性能优化方法
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 简单基于spring的redis配置(单机和集群模式)
  • 面试总结JavaScript篇
  • 使用parted解决大于2T的磁盘分区
  • 算法-图和图算法
  • 为视图添加丝滑的水波纹
  • 详解移动APP与web APP的区别
  • 小试R空间处理新库sf
  • 写给高年级小学生看的《Bash 指南》
  • 一个完整Java Web项目背后的密码
  • 仓管云——企业云erp功能有哪些?
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • # windows 运行框输入mrt提示错误:Windows 找不到文件‘mrt‘。请确定文件名是否正确后,再试一次
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #pragma once
  • $.ajax()参数及用法
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (论文阅读30/100)Convolutional Pose Machines
  • (每日一问)计算机网络:浏览器输入一个地址到跳出网页这个过程中发生了哪些事情?(废话少说版)
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。