Linux制作和使用动静态库

news2024/10/6 15:06:47

文章目录

  • 一、概念
    • 1.1 动态库和静态库
    • 1.2 动态链接和静态链接
  • 二、制作第三方库
    • 2.1 生成静态库
      • ① 制作静态库
      • ② 使用静态库
    • 2.2 生成动态库
      • ① 制作动态库
      • ② 使用动态库
  • 三、相关题目

一、概念

1.1 动态库和静态库

静态库与动态库本质都是一堆目标文件(xxx.o)的集合,库的文件当中并不包含主函数而只是包含了大量的方法以供调用。将程序编写成库提供给第三方使用,这样做的好处是不会造成源码泄漏,而且调用者不用关心内部实现。

  • 静态库(.a):程序在编译链接的时候把库的代码连接到可执行文件当中,运行时不再需要静态库。Linux中:前缀为"lib",后缀".a";Windows中:后缀".lib"。
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。Linux中:前缀为"lib",后缀".so";Windows中:后缀".dll。多个程序可以共享使用动态库代码。

ldd + 文件 显示可执行程序依赖的库

库名:去掉前缀lib 和 后缀及后面的版本号,才是库的名字。比如:libc.so.6,这个库为c动态库

一般服务器,可能没有内置语言的静态库,只有动态库,静态库需要我们手动安装。百度 yum安装C/C++静态库 sudo yum install glibc-static

静态库

静态库是程序在编译链接的时候把库的代码复制到可执行文件当中的,生成的可执行程序在运行的时候将不再需要静态库,因此使用静态库生成的可执行程序的大小一般比较大。

动态库

动态库是程序在运行的时候才去链接相应的动态库代码的,多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。

在可执行文件开始运行前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接。动态库在多个程序间共享,节省了磁盘空间,操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

image-20221009123054809

1.2 动态链接和静态链接

  • 动态链接:在可执行程序运行前,操作系统将使用到的动态库里的机器码从硬盘加载到内存中。gcc默认编译生成二进制程序的方式是动态链接。
  • 静态链接:可执行程序编译链接时,将代码使用到的静态库的代码拷贝到可执行程序中。在gcc编译命令后面加上 -static

查看链接方式:file + 可执行程序

静态链接和动态链接的优缺点:

静态链接:可执行程序文件体积大,特别是当有多个静态程序同时加载而这些静态程序使用的都是相同的库,这时在内存当中就会存在大量的重复代码。但是不依赖库,可移植性强。

动态链接:库执行程序文件体积小,多个用到相同动态库的程序同时运行时,库文件会通过进程地址空间进行共享,内存当中不会存在重复代码。但是依赖库,如果库被删除,该程序也就不可以使用了。

二、制作第三方库

2.1 生成静态库

① 制作静态库

静态库的本质:将所有的.o文件打包

静态库的生成有两个阶段:

  1. 用gcc -c 指令把源文件编译成.o的二进制文件
  2. 通过ar -rc 指令将将.o文件编译成静态库
    ar是gnu归档工具,rc表示(replace and creat)

image-20221009124249948

ar -tv 静态库,查看静态库内容,即包含了哪些二进制文件

  • t:列出静态库中的文件
  • v:verbose 详细信息

② 使用静态库

image-20221009124635438

lib下面有头文件和打包起来的库文件

命令行下去找静态库要有以下的命令

-I(大写i)+路径 指明头文件搜索路径

-L+路径 指明库文件搜索路径

-l(小写L)+库名称 指明要链接哪一个库,库名为去掉库文件前的lib和后缀就是库名。

gcc test.c -I./lib -L./lib -lmymath

我们之前写的C语言代码也用了库,但是为什么我们编译的时候不需要加上这些指令呢?

因为之前的库,在系统的默认路径下:/lib64,/usr/lib,/usr/include等。编译器能识别这些路径

换句话说,如果我不想带这些选项,我是不是可以把对应的库和头文件拷贝到默认路径下,没问题!但是极其不推荐,会污染别人写的文件!

上面的过程,也就是一般软件的安装过程!把人家的头文件和库下载到默认路径里

总结

我们交给别人的其实就是一个库文件+一批头文件

编写一个静态库:

  • 将源文件生成目标文件
  • 将所有目标文件打包成库文件。ar -rc 库文件名 目标文件

库要包含头文件打包的库文件。头文件可以直接获得。

使用静态库:

  • 编译的时候加上路径。

2.2 生成动态库

① 制作动态库

  • -shared:表示生成共享格式,用于最后生成可执行程序,该选项要在 -o前面。

    生成一个动态链接的共享库

  • -fPIC:产生位置无关码,用于编译生成 .o 目标文件,该选项在-c前面。

    程序内部的地址方案是:与位置无关,就是库文件可以在内存的任何位置加载,而且不影响和其他程序的关联性

  • 动态库名称规则:libxxx.so

image-20221009125341336

output就是我们的发布文件目录

② 使用动态库

image-20221009125628971

通过上面的这种方式我们可以成功的编译出可执行程序,但是当我们运行时会发现,这个程序不能运行:

[yzy@VM-4-4-centos friend]$ ./test 
./test: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory

因为上面只是告诉 编译器 头文件和库在哪里,当程序编译完成之后,就已经和编译无关了。

运行可执行程序的是加载器,我们要在运行程序的时候,进一步告知系统动态库在哪里。

解决方法

①动态库拷贝到系统默认路径下

推荐

LD_LIBRARY_PATH环境变量 -》 指明程序启动之后,动态库的搜索路径

echo $LD_LIBRARY_PATH查看

export LD_LIBRARY_PATH = 动态库所在路径,导入搜索路径

image-20221009130442223

将环境变量导入到~/.bashrc,不推荐,如果一定要改就多开几个终端防止写错

④全局配置

让环境变量每次都生效,/etc/ld.so.conf.d 搜索动态库的一个系统路径,我们可以进入到该文件夹里面添加路径

创建一个 XXX.conf文件,然后打开这个文件,往里面添加路径

image-20221009131156450

总结:

编写一个动态库:

  • 获得源文件和头文件
  • 将源文件生成目标文件,gcc -fPIC -o
  • 目标文件生成静态库,gcc -share -o *.so *.o

动态库:就是所有头文件和库文件

使用动态库:

  • 编译时要让编译器知道库文件路径,头文件路径和库名
  • 让系统知道库文件路径。添加环境变量。将库文件绝对路径加到LD_LIBRARY_PATH中。

如果只提供静态库,我们只能将我们的库,静态链接到我们的程序中

如果只提供动态库,我们只能将我们的库,动态链接到我们的程序中,如果加上 -static,也不能静态链接!

如果两种都想实现,一般需要提供两种版本的库文件!gcc 、g++优先链接动态库。

为什么我们之前写的所有代码都没有报错?默认是动态链接,因为我们一定有动态库!-》因为系统中有很多命令是C语言的写的,而且是动态链接的!

三、相关题目

1、下面哪一个不是动态链接库的优点?

A.共享

B.装载速度快

C.开发模式好

D.减少页面交换

解析

答案解析

动态链接链接的是动态库,而动态库中包含了大量的常用的功能接口指令代码

这种链接方式,是用于解决静态库存在的浪费内存和磁盘空间,以及模块更新困难等问题。

动态链接生成可执行程序,可执行程序中会记录自己依赖的库列表以及库中的函数地址信息,等到运行程序的时候,由操作系统将库加载到内存中(多个程序可以共享,不需要加载多份相同实例),然后根据库加载后的地址在对每个程序内部用到的库函数的地址进行偏移计算。

基于这么一种思想,动态链接具有以下优缺点:

优点

  • 更加节省内存并减少页面交换;
  • 库文件与程序文件独立,只要输出接口不变,更换库文件不会对程序文件造成任何影响,因而极大地提高了可维护性和可扩展性;
  • 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个库函数;
  • 适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。

缺点

  • 运行时依赖,否则找不到库文件就会运行失败
  • 运行加载速度相较静态库慢一些
  • 需要对库版本之间的兼容性做出更多处理

根据以上理解,题目为选择错误选项,因此选择B选项。


2、关于静态库与动态库的区别,以下说法错误的是()

A.加载动态库的程序运行速度相对较快

B.静态库会被添加为程序的一部分进行使用

C.动态库可用节省内存和磁盘空间

D.静态库重新编译,需要将应用程序重新编译

解析

动态库也叫运行时库,是运行时加载的库,将库中数据加载到内存中后,每个使用了动态库的程序都要根据加载的起始位置计算内部函数以及变量地址,因此动态链接动态库加载及运行速度相较静态链接是较为不如的,但是它也有好处,就是多个程序在内存中只需要加载一份动态库就可以共享使用。

静态链接,链接静态库,每个程序将自己在库中用到的指令代码单独写入自己可执行程序中,程序运行时无依赖,加载运行速度快,但是程序运行后有可能会有冗余代码在内存中

根据以上理解分析:

  • A错误 加载动态库的程序运行速度相对较慢,因为动态库运行时加载,映射到虚拟地址空间后需要重新根据映射起始地址计算函数/变量地址
  • B正确
  • C正确
  • D正确 动态链接的程序一旦库中代码发生改变,重新加载一次动态库即可,但是静态链接代码是写入程序中的,因此库中代码发生改变,必须重新链接生成程序才可以

而题目为选择错误选项,因此选择A选项


3、关于动态库和静态库以下描述正确的有()

A.gcc test.c -o libmytest.so 命令可以生成一个动态库

B.库文件中可以包含main函数

C.静态库使用gcc命令生成

D.库文件的链接可以使用-L选项指定所在路径,使用-l命令链接指定的库文件

答案解析

A选项错误,默认情况下,gcc test.c -o libmytest.so 生成的是一个可执行程序,而并非动态库, 若要生成动态库需要使用 -shared 选项进行指定

B选项错误,库文件是被其他程序引入使用的,因此不能有main函数,否则会与程序中的main函数产生冲突

C选项错误,静态库使用 ar 指令生成

D选项正确,gcc的-L选项用于指定链接库路径, -l选项用于链接指定库文件


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL 索引之道

文章目录1. 索引的介绍2. 索引的本质3. 索引的结构3.1 Hash3.2 B树3.3 常见面试题之为什么用B树4. 索引的分类4.1 功能逻辑层次4.2 存储形式层次5. 索引的失效5.1 最左前缀原则5.2 索引失效的场景6. 索引常见面试题7. 总结及参考文献1. 索引的介绍 索引是通过某种算法&#xf…

快速学习一门新技术的工作原理(十步学习法来自软技能)

快速学习一门新技术的工作原理 ●如何开始——要想开始使用自己所学的,我需要掌握哪些基本知识? ●学科范围——我现在学的东西有多宏大?我应该怎么做?在开始阶段,我不需要了解每个细节,但是如果我能对该学…

后台交互-首页

目录 后台准备 pom.xml 配置数据源 mybatis-generator 整合mybatis 准备前端的首页的数据 Promise 封装request 会议展示 后台准备 springbootmybatis pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://ma…

数据结构之链表(java语言实现)

链表的底层储存结构&#xff1a; 相对于数组这一需要连续、足够大空间的数据结构&#xff0c;链表只需要利用“指针”将一组零碎的空间(在链表中称之为节点)串联起来&#xff0c;这样就可以避免在创建数组时一次性申请过大的空间二导致有可能创建失败的问题!!! 同时比较两种数…

20221228英语学习

今日短文 Words and Phrases to Avoid in a Difficult Conversation Difficult conversations are difficult for a reason, and when you’re anxious or stressed out, it’s easy to say the wrong thing.And it doesn’t matter how prepared you are.Your best laid plan…

UDP协议与TCP协议详解

UDP协议详解 UDP&#xff0c;即User Datagram Protocol&#xff0c;用户数据报协议 UDP协议的特点&#xff1a;无连接&#xff0c;不可靠传输&#xff0c;面向数据报&#xff0c;全双工 无连接&#xff1a;知道对端的IP和端口号就直接进行传输&#xff0c;不需要建立连接&am…

深入讲解Linux中断子系统--Workqueue

说明&#xff1a; Kernel版本&#xff1a;4.14ARM64处理器&#xff0c;Contex-A53&#xff0c;双核使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 概述 Workqueue工作队列是利用内核线程来异步执行工作任务的通用机制&#xff1b;Workqueue工作队列可以用作中…

以前的互联网时代,其实就是一个以互联网技术为主导的年代

事实上&#xff0c;以往&#xff0c;我们所经历的那个互联网玩家频出的年代&#xff0c;其实就是一个以互联网技术为主导的年代。在那样一个年代里&#xff0c;互联网技术几乎是解决一切痛点和难题的万能解药&#xff0c;几乎是破解一切行业痛点和难题的杀手锏。任何一个行业&a…

使用Python读取网易邮箱大师客户端的所有邮件

文章目录1. 前言2. 效果3. 探究过程3.1. 找到本地存储的数据库3.2. 使用Python读取数据库3.2.1. 代码4. 探究结果4.1. 函数4.1.1. 找到特定邮~箱的最新一条邮件4.1.2. 找到特定邮箱的最新一次验证码4.1.3. 通过命令行调用Python代码找到特定邮箱的最新的验证码1. 前言 现在绝大…

中科大FPGAOL使用方法

1.中科大的FPGA在线平台提供了一个非常好用的功能&#xff0c;将bit文件上传到远程FPGA开发板上加以功能验证&#xff0c;而且可以游客的身份访问。 Login - FPGA Onlinehttp://fpgaol.ustc.edu.cn/ 2.系统采用的硬件平台是赛灵思的Nexys4 DDR开发板(xc7a100t-csg324)&#x…

RocketMQ学习(五):分布式事务

一、分布式事务 事务&#xff08;Transaction&#xff09;&#xff0c;一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言&#xff08;如SQL&#xff0c;C或Java&#xff09;…

『Java课设』JavaSwing+MySQL实现医院智慧点餐系统

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位喜欢写作&#xff0c;计科专业大三菜鸟 &#x1f3e1;个人主页&#xff1a;starry陆离 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 『Java课设』JavaSwingMySQL实现医院智慧点餐系统1.功能介…

设计模式:责任链模式的应用场景及源码应用

一、概述 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是将链中每一个节点看作是一个对象&#xff0c;每个节点处理的请求均不同&#xff0c;且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时&#xff0c;会沿着链的路径依次传递给每一个…

AI代码实时生成工具teleportHQ

来源&#xff1a;投稿 作者&#xff1a;ΔU 编辑&#xff1a;学姐 今天给大家分享一款AI代码实时生成工具teleportHQ&#xff0c;teleportHQ本质上是一个低代码开发平台&#xff0c;但是首次将计算机视觉应用到低代码开发上&#xff0c;teleportHQ允许用户通过熟悉的设计工具界…

JSX的基本使用

JSX的基本使用1.JSX简介1.1 JSX是react的核心内容1.2 createElement的问题1.3 createElement的问题1.4 JSX注意点2 使用prettier插件格式化react代码3 JSX中嵌入JavaScript表达式4 条件渲染5 列表渲染6 样式处理1.JSX简介 JSX是JavaScript XML的简写&#xff0c;表示了在Javas…

Linux 下 rpm管理包

一、 .rpm的文件格式 以.rpm格式发布的软件里面封装的都是经过编译过的二进制形式的软件&#xff0c;可以直接安装。.rpm格式的文件又称为rpm软件包&#xff0c;简称rpm包。 二、 rpm文件名的格式 三、 rpm命令的使用与软件的安装 Linux中安装rpm软件包有3种方法&#xff1…

新手小白入门之泛型

一、背景 JAVA推出泛型以前&#xff0c;程序员可以构建一个元素类型为Object的集合&#xff0c;该集合能够存储任意的数据类型对象&#xff0c;而在使用该集合的过程中&#xff0c;需要程序员明确知道存储每个元素的数据类型&#xff0c;否则很容易引发ClassCastException异常…

嵌入式书籍推荐

现在嵌入式软件工程师的数量需求方面是越来越旺盛&#xff0c;但是在人才供给方面却出现了缺口&#xff0c;个大公司对于嵌入式开发工程师职位出现供不应求的局面&#xff0c;正是有很多人看到这了大好的环境&#xff0c;纷纷选择开始学习嵌入式开发&#xff0c;学习的方式也是…

第十六讲:神州交换机访问控制列表的配置

访问控制列表ACL&#xff08;Access Control Lists&#xff09;数据定义工具&#xff0c;基于用户自行定义的数据的参数区分不同的数据流&#xff0c;是在交换机和路由器上经常采用的一种防火墙技术&#xff0c;它可以对经过网络设备的数据包根据一定规则进行过滤。它有以下一些…

CloudFlare 的路由拦截

因为腾讯需要对网站进行校验。 校验的方法是使用一个 tencent18250331897192314951.txt 文件&#xff0c;在这个文件中放入腾讯指定的内容。 我们使用的是 Discourse 这个社区系统&#xff0c;这个社区系统对这种问题的响应比较头痛。 解决方案 解决方案就是从域名服务商哪…