【Hello Linux】动态库和静态库(上)

简介: 【Hello Linux】动态库和静态库

引出

我们首先写出下面的一段很简单的c语言代码

1 #include <stdio.h>
  2 
  3 int main()
  4 {
  5   printf("hello world\n");                             
  6   return 0;
  7 }

这段代码我们在一开始学习c语言的时候就会写了 它的运行结果我们当然也很清楚 会向显示器打印 hello world

再回到上面的那段代码中 我们有没有想过这样一个问题

为什么我们调用 printf函数 就能够向屏幕打印信息呢?

通过前面基础IO和操作系统部分的学习

基础IO

操作系统

我们知道c语言其实是用户层的函数

它的下面有系统调用接口 系统调用接口经过封装之后变成为了我们的printf函数

而系统调用接口接受这个指令之后操作系统便指挥显示器的驱动向屏幕打印函数内的信息

也就是说我们在语言层面所直接使用的函数其实全部是别人封装好的(lib)

而我们上面的那段代码之所以可以运行就是因为gcc编译器在生成可执行文件的时候将c语言标准库连接了进来

初识动静态库

我们怎么查看自己使用了哪些库呢?

linux操作系统下 我们可以使用 ldd + 可执行文件名 来查看一个文件运行所依赖的库文件

这里面的 /lib64/lic.so.6 其实就是我们可执行程序所依赖的库文件

我们使用ls指令查看该库文件 发现它是一个文件的软连接

紧接着我们使用ll指令查看到该软连接的源文件

知道了该软连接的源文件之后我们可以使用file指令来查看它具体的文件类型

我们可以看到 它是一个共享的目标文件库 (shared object)被用作动态连接 (dynamically linked)

怎么辨认linux下的动静态库?

  • 在linux系统中动态库一般以.so为后缀 静态库一般以.a为后缀

顺便提一嘴

  • 在windows系统中动态库一般以.dll为后缀 静态库一般以.lib为后缀

库的名字是什么呢?

我们看到的库的源文件名字是 libc-2.17.so

我们去掉前面它的标识符lib 去掉后面的后缀.so 之后剩下的就是它的名字

即库的名字为 c-2.17

在默认情况下 我们编译程序都是使用动态连接的

如果我们想要进行静态链接则需要在后面加上一个-static选项

进行静态链接之后我们可以明显发现可执行文件的大小比动态链接的可执行文件大小大得多

这是因为使用静态链接编译可执行文件的话编译器会将整个库打包到可执行文件当中

我们可以使用 ldd + 静态链接后的文件名 来证明这一点

此外我们还可以使用file指令来查看它们是什么链接方式

动静态库的基本原理

动静态库的本质是可执行程序的“半成品”

我们都知道 语言从源文件变为可执行文件要分为下面四步

  1. 预处理 (去除注释 头文件展开 宏替换 条件编译)变成 .i 文件
  2. 编译 (将c/c++ 代码翻译成汇编代码)变成 .s 文件
  3. 汇编 (将汇编代码转化为二进制语言)变成 .o 文件
  4. 链接 (将汇编过程产生的二进制文件进行连接) 变成可执行文件

比如说 如果我们想要将五个源文件变为一个可执行文件的话我们就应该这么做

首先将这五个文件全部汇编变成.o目标文件

之后使用gcc编译器将这五个目标文件链接

而如果我们在别的项目中也需要用到这些二进制文件的话只需要复制一份过去之后用gcc编译器进行连接就可以

如果所有的项目几乎都要频繁的用到这几个目标文件呢?

那么我们实际上就可以对于这几个文件进行打包 放到环境配置中

每次要使用的时候自动到这个环境配置里面找

这样子打包后的文件就叫做库文件

所以说 各种动静态库的本质实际上就是一堆的目标文件(.o文件)

它们当中不包含main函数而是包含了大量的方法供使用者调用

这就是动静态库的原理 所以我们可以说动静态库的本质是可执行程序的“半成品”

动静态库的各自特征

我们将动静态库和可执行文件的概念映射到现实生活中

你在宿舍中写作业 动态库就像是网吧中的电脑

当你遇到不会的题目的时候 你就会去网吧查资料

而静态库就像是你在宿舍中买的电脑

当你遇到不会的题目的时候 你就会使用自己的电脑去查资料

静态库

静态库链接就是程序在编译连接的将静态库中的代码下载到可执行文件当中

所以说我们使用静态库生成的可执行文件一般体积比较大

自然可执行程序运行的时候也不需要依赖外部库文件了

  • 优点

使用静态库链接之后 文件不需要依赖外部库文件也可以执行

  • 缺点

使用静态库链接的库文件体积较大 占用空间多 且多个静态链接的可执行文件中可能会有大量的重复代码

动态库

动态库链接是程序在运行的时候才去链接相应的动态库代码 多个程序共享使用库的代码

在可执行文件开始运行前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存当中 这个过程被称为动态链接

为了节省空间 操作系统利用虚拟内存机制 将中间的一片共享区指向了物理内存中同一块动态库区域

  • 优点

节省磁盘空间 避免重复代码

  • 缺点

依赖库文件运行 如果缺少库文件则无法运行

相关文章
|
3月前
|
安全 Linux vr&ar
Linux的动态库和静态库
Linux的动态库和静态库
|
1月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
84 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
3月前
|
Linux API
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
|
4月前
|
Oracle 关系型数据库 Linux
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
通过这一连串的步骤,可以专业且有效地在Linux下为Qt编译Oracle驱动库 `libqsqloci.so`,使得Qt应用能够通过OCI与Oracle数据库进行交互。这些步骤适用于具备一定Linux和Qt经验的开发者,并且能够为需要使用Qt开发数据库应用的专业人士提供指导。
149 1
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
|
3月前
|
Linux 网络安全 API
【Azure 应用服务】App Service For Linux 环境中,如何从App Service中获取GitHub私有库(Private Repos)的Deploy Key(RSA key)呢?
【Azure 应用服务】App Service For Linux 环境中,如何从App Service中获取GitHub私有库(Private Repos)的Deploy Key(RSA key)呢?
|
3月前
|
小程序 Linux 开发者
Linux之缓冲区与C库IO函数简单模拟
通过上述编程实例,可以对Linux系统中缓冲区和C库IO函数如何提高文件读写效率有了一个基本的了解。开发者需要根据应用程序的具体需求来选择合适的IO策略。
32 0
|
4月前
|
Linux 编译器 vr&ar
【Linux】静态库和动态库
本文详细介绍了Linux系统中静态库和动态库的概念、区别、制作与使用方法,包括它们在链接时的区别、加载机制以及优缺点。
54 0
|
4月前
|
Linux Shell vr&ar
【linux】详解——库
【linux】详解——库
|
6月前
|
Linux vr&ar C语言
|
6月前
|
存储 Linux 编译器
Linux静态库与动态库的使用
Linux静态库与动态库的使用
下一篇
无影云桌面