Linux之静态库和动态库

目录

一、前言

二、对于库的理解

三、静态库

四、动态库

五、动静态库的加载


一、前言

在之前,我们讲了静态库和动态库,详情请跳转:静态库和动态库

下面我们将从工程师的角度,去了解静态库和动态库的形成过程,以及实现它们的制作。并且了解如何将自己的库交给别人,让别人也可以使用。

二、对于库的理解

Linux的库一般分为动态库和静态库:

静态库:库文件以 .a 为后缀,程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。

动态库:库文件以 .so 为后缀,程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

gcc 在编译时默认使用动态链接,链接动态库,而如果想生成静态链接,我们需要在末尾带上 -static。

而我们知道,程序编译链接的最后,其实就是将各种 .o 可重定位目标二进制文件包括 main 函数的 .o文件,与所包含的 .h 文件全部链接起来,形成可执行程序。所以,这是不是就意味着,用户真正需要的库文件其实是 .o 文件,设计者可以不用将源文件提供给用户,而直接将.o和.h文件提供给用户,以供用户链接。这样不仅方便,而且能够保护源码。这样可以吗?

如下图,在该目录下,我们只有.h和.o文件,没有这些文件的源码。那么能编译成功吗?

编译结果如下:

我们发现,编译出的可执行程序能够运行。 

但是如果存在很多.c文件呢?难道我们要把几千个.c文件全部编译成.o在加上头文件全部一个一个提供吗?那样太过于麻烦,为了让用户更好的使用库,我们就有把所有的.o文件打成一个包,给对方提供一个库文件。

所以,库中包含了多个.o文件。

三、静态库

我们可以使用 ar 命令(把所有的.o打包起来),来制作一个静态库。比如:我们要打包二中所讲到的.o文件:

ar -rc libexe.a myadd.o myprintf.o

当然,我们也可以写一个Makefile来快速制作一个库。

output:而我们要交付库,实际上要把库文件 .a 以及匹配的头文件都交付给用户,而output就相当于一个发布的过程。

好了,那么静态库我已经制作好了,且已经发布了,那么我们来使用一下自己制作的库。首先,我们将库拷贝到 mylib 目录下去使用。

但是,当我们编译时,却出错了:

gcc在编译时,找不到头文件!!! 

解决方法:编译器搜索头文件时默认在当前目录下搜索,在系统默认指定路径下搜索。虽然此时的mylib在当前路径下,但是头文件太深了,编译器找不到头文件,所以我们需要给gcc指定路径。如下:使用选项 -I 告诉编译器头文件所在路径。

问题又来了,gcc找不到库函数的实现。我们在形成可执行程序的时候,库文件要使用的话也要知道库所在的路径在哪里,系统的默认路径是/lib64,而这是我们自己制作的库,不在里面。所以我们要带上 -L。告诉库的路径在哪里。因为该路径下可能有多个库,所以我们还要使用 -l 选项,加上库名字去掉前缀和后缀 .a。

 如上图,我们编译并且运行成功了。

总结:

-I:指明头文件的搜索路径

-L:指明库文件的搜索路径

-l:指明要链接哪个库,带上库的名称(去掉前缀和后缀)

四、动态库

首先我们需要把库文件全部编译成.o文件,这里与静态库不同,需要带上选项 -fPIC,形成与位置无关码。我们还是以上面的文件为例:

gcc -fPIC -c myadd.c -o myadd.o
gcc -fPIC -c myprintf.c -o myprintf.o

 

 动态库打包需要加上选项:-shared。

gcc -shared myprintf.o myadd.o -o lib.so

我们可以建立一个makefile,同时形成静态库和动态库。

 

然后我们发布:

接下来,我们就来使用一下我们自己制作的动态库。

 下图中,我们编译成功,且形成了可执行程序。 

但是,当我们运行可执行程序时,却失败了:

因为我们的lib目录下,既有动态库,也有静态库,所以gcc在编译时默认使用的是动态库。可是,既然我已经指明了库所在的路径,那为什么在运行可执行程序时还会动态链接失败呢?

原因就是:那只是在编译时,告诉了gcc编译器动态库在哪里,然后编译成功且形成了可执行程序,如果你在编译时没有告诉库在哪,编译就不会成功,且不会形成可执行程序。而我们运行可执行程序是由操作系统加载到内存来运行的,运行时也需要告诉操作系统库在哪里。我们还没有告诉操作系统动态库在哪里呢!!!

解决方法:

1、添加到环境变量里:把库路径添加到环境变量LD_LIBRARY_PATH

比如:我的动态库所在路径为:/home/zdl/mylib/output/lib

但是我们自己定义的环境变量只是本次登录有效,如果想永久有效只能修改环境变量的配置,但是比较麻烦。想永久有效,我们还有其他的方法。 

2、配置文件(/etc/ld.so.conf.d/):动态库进行对应搜索时可以采用自己定义conf文件找到动态库

直接在该路径 /etc/ld.so.conf.d/ 下创建一个以.conf为后缀的文件。

然后将动态库所在的路径添加到文件中即可。

最后,使用sudo ldconfig使文件生效。 

3、建立软链接直接找到对应的库

可以将库的路径建立软链接到 /lib64/ 路径下。

五、动静态库的加载

静态库:静态库是直接将自己的代码和数据拷贝到可执行程序中,然后随可执行程序一同加载到内存中。它们相当于已经是一体的了。静态库的代码随可执行程序的代码一起加载到程序地址空间的代码区。

动态库:动态库可以和可执行程序分批加载。

动态库加上fPIC选项形成位置无关码,采用相对编址的方法,在程序链接时对应库当中的偏移量添加到可执行程序,运行时一旦库加载进来,经过地址空间映射,把库映射到地址空间之后,库也就具备了起始地址,通过偏移地址和起始地址这样就可以找到访问的函数。

具体过程:可执行程序在运行时,如果遇到某处代码需要调用库的方法,库的代码和数据就会加载到物理内存中,然后将你需要使用的方法通过页表映射到共享区。然后代码直接到共享区去找,再通过页表找到物理内存中的具体方法,使用完后,代码继续向后执行,如又遇到库里的方法,就再去找。

如果有多个进程需要使用同一个库,那么其他的进程可以直接通过页表和物理内存中的代码直接建立联系。所以动态库加载一次就可以被多个进程共同使用了。

而静态库可能有多个程序用了C库,加载到内存时,内存里可能会存在很多份重复的代码。而动态链接不会出现重复的代码,减少内存占用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/319099.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android平台RTMP推送|轻量级RTSP服务|GB28181设备接入模块之实时快照保存JPG还是PNG?

JPG还是PNG? JPG和PNG是两种常见的图片文件格式,在压缩方式、图像质量、透明效果和可编辑性等方面存在显著差异。 压缩方式:JPG是一种有损压缩格式,通过丢弃图像数据来减小文件大小,因此可能会损失一些图像细节和质量…

华为设备登录安全配置案例

知识改变命运,技术就是要分享,有问题随时联系,免费答疑,欢迎联系! 厦门微思网络​​​​​​ https://www.xmws.cn 华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle O…

【现代密码学】笔记9-10.3-- 公钥(非对称加密)、混合加密理论《introduction to modern cryphtography》

【现代密码学】笔记9-10.3-- 公钥(非对称加密)、混合加密理论《introduction to modern cryphtography》 写在最前面8.1 公钥加密理论随机预言机模型(Random Oracle Model,ROM) 写在最前面 主要在 哈工大密码学课程 张…

Java Http各个请求类型详细介绍

1. 前言 在Spring Boot框架中,HTTP请求类型是构建Web应用程序的重要组成部分。常见的请求类型包括GET、POST、PUT和DELETE,每种类型都有其特定的用途和特点。本文将详细比较这四种请求类型,帮助您在开发过程中做出明智的选择。 2. GET请求…

Java SPI在数据库驱动、SpringBoot自动装配中的应用

文章目录 1. 初识SPI1.1 SPI的作用1.2 SPI的工作原理1.3 SPI的三个组件:Service、Service Provider、ServiceLoader1.4 SPI使用场景1.5 具体的SPI 源码分析(SPI的核心就是ServiceLoader.load()方法)1.6 SPI 的优缺点 2. API、SPI、JNDI释义3.…

《工具录》fierce

工具录 1:fierce2:选项介绍3:示例 本文以 kali-linux-2023.3-vmware-amd64 为例。 1:fierce fierce 是开源的网络安全工具,用于进行域名扫描和子域名枚举。 官方网址:https://github.com/mschwager/fierc…

基于springboot时间管理系统源码和论文

在Internet高速发展的今天,我们生活的各个领域都涉及到计算机的应用,其中包括时间管理系统的网络应用,在外国时间管理系统已经是很普遍的方式,不过国内的管理系统可能还处于起步阶段。时间管理系统具有时间管理功能的选择。时间管…

做好岗位设计,提升组织效率

科学地划分每个岗位,让员工明确自己的岗位职责,这样有利于提升组织的效率,减少无用功,充分发挥所有员工的正向作用。 案例素材来源于网络整理 某市电视台广告部审核科的主要职责是:广告内容审核、广告合同审核、广告播…

理解TCP/IP协议

一、协议 在计算机网络与信息通讯领域里,人们经常提及 “协议” 一词。互联网中常用的协议有HTTP、TCP、IP等。 协议的必要性 简单来说,协议就是计算机与计算机之间通过网络通信时,事先达成的一种 “约定”。这种“约定”使不同厂商的设备…

将图片添加到 PDF 的 5 种方法

需要一种称为 PDF 编辑器的特定工具才能将图片添加到 PDF。尽管大多数浏览器在查看和注释 PDF 文件方面都非常出色,但如果您使用图像到 PDF 技术,则只能将照片放入 PDF 中。无需修改即可将 PDF 文件恢复为原始格式的能力是使用此类软件程序甚至在线服务的…

Ensp AR/WLAN设备启动失败问题 错误代码41 解决方案

现象描述 启动AR设备之后,设备命令行无法接收输入,在长时间等待后一直输出“####”。启动AR/WLAN设备时,提示“…错误代码40…”。 检查虚拟网卡设置。 检查安装eNSP的PC上是否存在名为“VirtualBox Host-Only Network”的虚拟网卡。 - 如果…

MyBatis第三课

目录 回顾 #和$区别 #(预编译SQL)和$(即时SQL,它是进行的字符串拼接)的区别,其中之一就是预编译SQL和即时SQL的区别 原因: 回顾 两者的共同点 MaBits可以看作是Java程序和Mysql的沟通桥梁&…

[Kubernetes]7. K8s包管理工具Helm、使用Helm部署mongodb集群(主从数据库集群)

上一节讲解了[Kubernetes]6. k8s Pod配置管理ConfigMap & Secret以及传递环境变量的使用,k8s的命名空间以及使用kubens管理命名空间的使用,这里来介绍一下Helm的使用 一.Helm相关介绍 1.介绍 在 kubernetes 系统上部署容器化应用时需要事 先手动编写资源配置清单文件 以…

06-微服务OpenFeigh和Sentinel持久化

一、OpenFeign基础应用 1.1 概念 OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访…

遭受慢速连接攻击怎么办?怎么预防

慢速连接攻击是一种常见的网络攻击方式,其原理是利用HTTP协议的特性,在建立了与Http服务器的连接后,尽量长时间保持该连接,不释放,达到对Http服务器的攻击。 慢速连接攻击的危害包括以下几个方面: 1.资源…

LeetCode刷题--- 删除并获得点数

个人主页:元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 ​​​​​​http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​http://t.csdnimg.cn/hKh2l 前言:这个专栏主要讲述动…

学习Java API(一):基础知识点一文通✅

推荐阅读 智能化校园:深入探讨云端管理系统设计与实现(一) 智能化校园:深入探讨云端管理系统设计与实现(二) 文章目录 推荐阅读API文档注释String类创建字符串拼接字符串格式化字符串String方法substring(…

SVN切换账户

前言(svn切换) 本文章简单写下SVN账户切换操作 linux 1.删除目录 ~/.subversion/auth/ 下的所有文件。 2.再次操作svn时可重新输入用户名和密码。 windows (1)在工程中单击右键,单击"TortoiseSVN"。 (2)选择"Setting"。 (3)选择&quo…

数据结构【树+二叉树】

目录 线性表和非线性表 树的概念 树的存储表示 二叉树的概念 特殊二叉树 满二叉树 完全二叉树 二叉树的性质 二叉树的存储结构 顺序存储 链式存储 本篇我们开始进入数据结构中【树】的学习。 线性表和非线性表 逻辑结构:人想象出来的物理结构&#xf…

计算机硬件 5.1机箱与电源

第五章 其他设备 第一节 机箱与电源 一、认识电源 1.功能:将普通交流电转换为直流电,再控制电压分别输出给不同部件。 2.分类: 3.供电插头: ①8Pin插头:为高档PCI-E显卡供电,或为较新的CPU供电&#xff…
最新文章