【基础IO】动静态库 {动静态库的创建和使用;动静态库的加载;默认优先使用动态链接;为什么要有库;动态链接的优缺点;静态链接的优缺点;一些有趣的库}

在这里插入图片描述

一、静态库(.a)

1.1 如何创建静态库?

  1. 编写源文件与头文件。注意:库的源文件没有main函数!

在这里插入图片描述

  1. 将所有的源文件编译生成目标文件。(如果只提供.h和.o给用户,用户也可以成功编译运行。但这样的做法太过麻烦,且容易出错。)

在这里插入图片描述

  1. 利用ar工具将所有的目标文件归档生成静态库。注意:静态库文件的前缀是lib后缀是.a!

在这里插入图片描述

提示:ar是gnu归档工具,用于归档生成静态库。rc选项表示replace and create。

  1. 打包发布静态库:为静态库创建目录,并将头文件和库文件分开存放。

在这里插入图片描述

  1. 自动化生成并发布静态库
    在这里插入图片描述

1.2 如何使用静态库?

先将静态库拷贝给用户

在这里插入图片描述

方法一:

  1. 将头文件和库文件直接拷贝到系统的默认搜索路径下

    • gcc头文件的默认搜索路径:/usr/include

    • gcc库文件的默认搜索路径:/lib64 or /usr/lib64

    在这里插入图片描述

  2. gcc会自动链接C静态库(libc.a),第三方库需要带-l选项指定要链接的库。注意:这里的库名称是要去掉lib前缀和.a后缀的!

    在这里插入图片描述

提示:我们将库拷贝到系统默认搜索路径下的操作,就叫做库的安装!

方法二:通过-I-L选项指定头文件和库文件的所在路径,并用-l指明要链接的库

在这里插入图片描述


二、动态库(.so)

2.1 如何创建动态库?

  1. 编写源文件与头文件。注意:库的源文件没有main函数!
  2. 将所有的源文件编译生成目标文件。注意:生成动态库的目标文件要加-fPIC选项,生成与位置无关的目标文件

在这里插入图片描述

提示: 动态库的目标文件需要是位置无关代码,所谓位置无关代码是一种可在内存中的任意位置加载和执行的代码,它不依赖于特定的内存地址。(详细解释请转到【动态库的加载】)

  1. 通过gcc -shared命令将所有的目标文件归档生成动态库。注意:动态库文件的前缀是lib后缀是.so!

在这里插入图片描述

  1. 打包发布动态库:为动态库创建目录,并将头文件和库文件分开存放。(此处包含静态库)

在这里插入图片描述

  1. 自动化生成并发布动态库(此处包含静态库)
    在这里插入图片描述

2.2 动静态库的加载

在这里插入图片描述
静态库的加载

  1. 静态库代码会同程序代码合并在一起进行编译和编址形成可执行程序,程序运行时可执行程序被程序加载器加载到物理内存,并通过页表映射到进程地址空间,程序的代码会被映射到的代码区,全局变量会被映射到静态区。
  2. 静态库代码采用绝对编址的方式,其全局变量和函数的虚拟地址在编译和链接时就已经确定,这个地址是固定的线性地址,不管程序运行多少次,运行多少个实例,它的地址始终是确定的,而且是唯一的线性地址。

动态库的加载

  1. 动态库并没有被合并到可执行程序中,动态库与可执行程序是被分批加载到物理内存中的。
  2. 动态库被进程首次调用时,动态库代码会被动态库链接器加载到物理内存,并通过页表建立与地址空间的映射关系。动态库的全局变量和函数都会被映射到地址空间的共享区。
  3. 动态库代码采用相对编址的方式,其全局变量和函数在编译和链接时分配到的地址是相对地址(相对库起始地址的偏移量)。也就是说动态库代码与位置无关,每次运行程序,运行不同的实例,都可能会被映射到不同的虚拟地址处。
  4. 库的运行时虚拟地址(变化的) = 库的起始虚拟地址(变化的) + 库的相对地址(编译链接时分配);
  5. 如果有多个进程同时调用了同一个动态库,该动态库只需要向内存加载一次。之后凡是调用该动态库的进程只需要计算运行时地址,建立页表映射关系即可。因此,动态库也被成为共享库。

2.3 动态库的使用

先将动态库拷贝给用户

在这里插入图片描述

方法一:

  1. 安装库:将头文件和库文件直接拷贝到系统的默认搜索路径下
  2. 编译程序,带-l选项指定要链接的库

方法二:

  1. 通过-I-L选项指定头文件和库文件的所在路径,并用-l指明要链接的库

    在这里插入图片描述

    为什么动态链接后会报错:找不到动态库文件?就是因为动态链接器的运行时链接库缓存中没有对应动态库的路径。

  2. 向动态链接器缓存中添加动态库路径

    1. 可以将动态库拷贝到/lib64路径下,加载器默认会在该路径下进行搜索。

      在这里插入图片描述

    2. 我们还可以在/lib64路径下创建动态库文件的软链接。

      在这里插入图片描述

    3. 还可以在环境变量LD_LIBRARY_PATH中添加动态库的所在路径,加载器也会在环境变量中的路径下搜索动态库。
      在这里插入图片描述

      注意:修改环境变量,只是修改了bash缓冲区中的内容。只在本次登录中有效

    4. 还可以在bash的资源配置文件.bashrc中,添加登录时导入LD_LIBRARY_PATH环境变量的操作。

    5. 我们还可以通过在/etc/ld.so.conf.d/目录下添加配置文件的方法,永久性的添加动态库的搜索路径。

      在这里插入图片描述

      提示:ldconfig是一个用于配置动态链接器运行时的命令。它用于更新动态链接器的运行时链接库缓存,以便在程序运行时能够正确地找到和加载动态库。


三、默认优先使用动态链接

此时的lib目录下既有动态库(.so)又有静态库(.a),编译链接的程序是动态链接还是静态链接?

  1. 如果目录下只有静态库:有动态库就动态链接,没有动态库也只能静态链接。(此时lib目录下没有libmylib.so)
    在这里插入图片描述
  2. 如果目录下动静态库同时存在,gcc默认优先使用动态链接。
    在这里插入图片描述
  3. 如果动静态库同时存在,非要使用静态库呢?-static选项:摒弃默认优先使用动态库的原则,所有库都直接使用静态链接方案。
    在这里插入图片描述

四、为什么要有库?

  • 站在使用者的角度:库的存在可以大大减少使用者的开发周期;同时使用高质量的库还可以提高软件本身的质量。

  • 站在开发者的角度:可以使合作开发更加简单;同时也隐藏了源码,提高了代码安全性。

3.1 静态链接的优缺点

优点:

  1. 独立性:静态链接使得可执行文件成为一个独立的实体,不需要依赖外部的库文件。这意味着可执行文件可以在没有其他依赖项的情况下运行,更加方便和可移植。
  2. 简单部署:由于静态链接将所有依赖项都打包到可执行文件中,部署和分发可执行文件变得更加简单。只需将可执行文件复制到目标系统上,而不需要担心库文件的版本兼容性或缺失。
  3. 性能优化:静态链接可以在编译时进行优化,将库的代码和数据与主程序一起进行优化和整合。这可以提高程序的执行效率和性能,因为编译器可以进行更多的优化和内联操作。

缺点:

  1. 内存占用:静态链接会导致每个可执行文件都包含其所需的库和依赖项的副本,这会占用更多的内存空间。如果多个程序同时使用相同的库,每个程序都需要加载和占用相同的库的副本,造成内存浪费。
  2. 更新和维护:静态链接的可执行文件中包含了所有的库和依赖项,当库或依赖项发生更新时,需要重新编译和重新部署整个可执行文件。这增加了更新和维护的复杂性,尤其是在大型项目中或者涉及多个依赖项的情况下。
  3. 文件大小:由于静态链接将所有的库和依赖项都打包到可执行文件中,导致可执行文件的大小增加。这可能会增加程序的下载时间和存储空间的消耗。

3.2 动态链接的优缺点

优点:

  1. 节省内存:动态链接允许多个程序共享同一个库的实例,避免了每个程序都加载和占用相同库的副本,从而节省了内存空间。
  2. 减少页面交换:当使用动态链接时,操作系统只需要将库文件的代码和数据加载到内存中一次,然后多个程序可以共享这些库的实例。这减少了需要从磁盘加载和卸载库文件的次数,减少了页面交换的频率。
  3. 灵活更新:当库文件发生更新时,只需要更新库文件本身,而不需要重新编译和部署整个程序。这样可以简化更新和维护的过程,节省时间和资源。
  4. 减少程序体积:由于库文件是独立存在的,可执行文件只需要包含自身的代码和数据,因此可执行文件的体积相对较小。

缺点:

  1. 运行时依赖:动态链接需要依赖外部的库文件,如果库文件缺失或版本不兼容,程序可能无法正常运行。这增加了程序在不同环境中的部署和兼容性的挑战。
  2. 性能损失:动态链接需要在运行时加载和链接库文件,这会引入一定的性能开销。相比静态链接,动态链接的程序可能稍微慢一些。
  3. 部署复杂性:动态链接需要确保系统中存在正确的库文件,并设置正确的库路径。这可能需要额外的配置和管理工作,增加了部署的复杂性。

3.3 一些有趣的库

  1. ncurses:字符界面库

    ncurses库是一个用于创建基于终端的交互式应用程序的库。它提供了一套API,用于处理终端界面的输入和输出,以及控制终端的光标位置、颜色、窗口等。

    使用ncurses库,您可以在终端中创建复杂的文本界面,包括窗口、菜单、按钮、文本框等。您可以使用函数来控制光标的位置,以及在终端上输出文本和图形。此外,ncurses库还提供了处理键盘和鼠标输入的功能,以及对终端的颜色和属性进行控制。

    ncurses库的安装和使用请看这篇文章:【Linux拓展】ncurses库的安装和使用 {ncurses库的安装方法,ncurses库的使用手册,基于终端的贪吃蛇游戏}_芥末虾的博客-CSDN博客

  2. Boost:C++准标准库

    Boost是一个开源的、跨平台的C++库集合,提供了许多高质量、可移植且广泛使用的组件和工具,涵盖了从基本的数据结构和算法到高级的并发编程和网络编程等各个领域。

    Boost库的特点包括:

    1. 高质量:Boost库的组件经过了严格的测试和评审,具有高质量和稳定性,广泛应用于工业和学术界。

    2. 可移植性:Boost库的组件可以在多个平台上运行,包括Windows、Linux、Mac等。

    3. 开源:Boost库是开源的,可以免费使用和修改。

    Boost库提供了丰富的功能,包括但不限于以下几个方面:

    1. 智能指针:Boost库提供了多种智能指针,如shared_ptr、scoped_ptr等,用于管理动态分配的内存,避免内存泄漏和悬空指针等问题。

    2. 容器和算法:Boost库提供了许多扩展了标准库的容器和算法,如unordered_map、unordered_set、foreach等,方便开发者进行数据处理和算法实现。

    3. 并发编程:Boost库提供了多线程、原子操作、线程池等并发编程的工具和组件,简化了多线程编程的复杂性。

    4. 正则表达式:Boost库提供了强大的正则表达式库,支持正则表达式的匹配、替换、分割等操作。

    5. 文件系统:Boost库提供了对文件系统的操作接口,方便开发者进行文件和目录的创建、删除、遍历等操作。

    6. 网络编程:Boost库提供了网络编程的工具和组件,包括TCP/UDP套接字、异步IO、网络协议等,方便开发者进行网络应用的开发。

    总之,Boost库是一个功能强大、广泛应用的C++库集合,可以提高开发效率,增加代码的可靠性和可移植性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芥末虾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值