【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函数而是包含了大量的方法供使用者调用

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

动静态库的各自特征

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

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

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

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

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

静态库

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

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

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

  • 优点

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

  • 缺点

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

动态库

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

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

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

  • 优点

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

  • 缺点

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

相关文章
|
6天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
24 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
1月前
|
Linux
linux 交叉编译libpng,libjpeg库
linux 交叉编译libpng,libjpeg库
23 1
|
1月前
|
Linux 编译器 Android开发
linux交叉编译nss3,nspr库精讲
linux交叉编译nss3,nspr库精讲
37 1
|
1月前
|
Linux 编译器 vr&ar
linux交叉编译一些常用依赖库util-linux,zlib,sqlite3,eudev ,openssl,libpng,glibc
linux交叉编译一些常用依赖库util-linux,zlib,sqlite3,eudev ,openssl,libpng,glibc
31 1
|
7天前
|
Linux 网络安全 开发工具
【GitLab私有仓库】在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透
【GitLab私有仓库】在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透
|
1月前
|
Shell Linux vr&ar
【Shell 命令集合 备份压缩 】⭐⭐⭐Linux 修改备存/静态库 文件 ar命令 使用指南
【Shell 命令集合 备份压缩 】⭐⭐⭐Linux 修改备存/静态库 文件 ar命令 使用指南
30 0
|
1月前
|
缓存 算法 Linux
深入理解Linux动态库加载:路径、问题与解决方案
深入理解Linux动态库加载:路径、问题与解决方案
83 0
|
1月前
|
Linux 编译器 网络安全
linux 交叉编译libcurl库
linux 交叉编译libcurl库
37 1
|
1月前
|
算法 安全 Linux
Linux 裁剪并交叉编译openssl库
Linux 裁剪并交叉编译openssl库
34 1
|
1月前
|
Linux 编译器 vr&ar
【Linux】—— 详解动态库和静态库
【Linux】—— 详解动态库和静态库