Linux学习之制作静态库和动态库

写在前面:

我的Linux的学习之路非常坎坷。第一次学习Linux是在大一下的开学没多久,结果因为不会安装VMware就无疾而终了,可以说是没开始就失败了。第二次学习Linux是在大一下快放暑假(那个时候刚刚过完考试周),我没什么事做就又重拾Linux,不服输的我选择再战Linux,这一次学习还算顺利,虽然中间有些小插曲但是不影响整体学习进度, 我看着B站上的视频一点点学习Linux,基本上把Linux的基础指令学完了。学完之后我又遇到问题了,视频基本上到这就结束了,而我却不知道下一步该学什么,于是就没怎么碰Linux,结果没过多长时间我就把学的Linux指令忘的一干二净。现在是我第三次学习Linux,我决定重新开始学Linux,同时为了让自己学习的效果更好,我选择以写blog的形式逼迫自己每天把学习到的Linux知识整理下来。这也就是我写这个系列blog的原因。

动态库和静态库的理论对比

  • 静态库在文件中静态展开,所以有但多少文件就展开多少次,非常吃内存,100M的文件展开一百次就是1G。但是这样的好处是静态加载的速度快
  • 动态库使用时,会讲动态库加载到内存,10个文件也只需要加载一次,然后将这些文件用到库时候临时去加载,速度慢一些但是很省内存
    Linux学习之制作静态库和动态库_第1张图片

静态库的制作

  1. 写好源代码。下面我以写一个可以四则运算的静态库的为例)
    Linux学习之制作静态库和动态库_第2张图片

  1. 编译源代码生成 .o文件。
    Linux学习之制作静态库和动态库_第3张图片

可能有些童鞋没学过编译的四个过程,下面我来介绍一下

  1. 预处理: 展开宏,头文件,替换编译条件,删除注释,空行,空白。
  2. 编译: 检查语法规范。
  3. 汇编: 将汇编指令翻译成机器指令。
  4. 链接: 数据段合并,地址回填。

Linux学习之制作静态库和动态库_第4张图片


关于gcc常用的编译参数

  • -I:指定头文件所在目录位置。
  • -c:只做预处理,编译,汇编。得到二进制文件。
  • -g:编译时添加调试文件,用于 gdb 调试。
  • -Wall:显示所有警告信息。
  • -D:向程序中“动态”注册宏定义
  • -L:指定动态库路径。
  • -l:指定动态库库名。

  1. 制作静态库
    命令:ar rcs lib库名.a file1.o file2.o ...
    3

  1. 制作头文件
    如果我们直接使用静态库gcc test.c lib库名.a -o a.out,就会有以下警告。
    Linux学习之制作静态库和动态库_第5张图片
    为了防止出现以上警告,我们就要做一个头文件来包含函数声明(当然你也可以直接在test中声明,但这体现我们的水平)
    Linux学习之制作静态库和动态库_第6张图片

左边的 define 为头文件守卫,防止在代码中多次 include 头文件,多次展开静态库,带来的额外开销

接下来我们再来编译,这样就不会就有警告报错了。
Linux学习之制作静态库和动态库_第7张图片

最后-I ...是写头文件的地址


动态库的制作

  1. 编写源代码
    Linux学习之制作静态库和动态库_第8张图片

  1. 生成位置无关的.o 文件
    命令:gcc -c add.c -o add.o -fPIC

使用这个参数-fPIC过后,生成的函数就和位置无关,挂上@plt 标识,等待动态绑定
Linux学习之制作静态库和动态库_第9张图片


  1. 使用制作动态库
    命令:gcc -shared -o lib库名.so file1.o file2.o ....
    Linux学习之制作静态库和动态库_第10张图片

  1. 编译程序
    命令:gcc test,c -o test -l 库名 -L 路径 -I 头文件的位置

  1. 执行文件,然后出错。
    Linux学习之制作静态库和动态库_第11张图片

  1. 出错原因及解决方法
  • 出错原因分析:
    • 连接器:工作于链接阶段,工作时需要 -l 和 -L
    • 工作于程序运行阶段,工作时需要提供动态库所在目录位置
  • 解决方法:
    1. 通过环境变量指定动态库所在位置:export LD_LIBRARY_PATH=动态库路径。但是这个方法有个弊端,当关闭终端,再次执行a.out 时,又报错。这是因为,环境变量是进程的概念,关闭终端之后再打开,是两个进程,环境变量发生了变化。
      3
    2. 写入终端配置文件。 步骤如下:
      • vi ~/.bashrc
      • 写入 export LD_LIBRARY_PATH=动态库路径
      • . .bashrc/ source 或者.bashrc / 或者重启 终端 —> 让修改后的.bashrc 生效
      • ./a.out 成功!!!
    3. 配置文件法。步骤如下:
      • sudo vi /etc/ld.so.conf
      • 写入 动态库绝对路径 保存
      • sudo ldconfig -v 使配置文件生效。
      • ./a.out 成功!!!— 使用ldd a.out查看

写在最后

个人亲身经验:我们学习的一系列Linux命令,一定要自己亲手去敲。不要只是看别人敲代码,不要只是停留在眼睛看,脑袋以为自己懂了,等你实际上手去敲会发现许许多多的这样那样的问题。正可谓“键盘敲烂,月薪过万


如果你觉得我写题解还不错的,请各位王子公主移步到我的其他题解看看

  1. 数据结构与算法部分(还在更新中):
  • C++ STL总结 - 基于算法竞赛(强力推荐
  • 动态规划——01背包问题
  • 动态规划——完全背包问题
  • 动态规划——多重背包问题
  • 动态规划——分组背包问题
  • 动态规划——最长上升子序列(LIS)
  • 二叉树的中序遍历(三种方法)
  • 最长回文子串
  • 最短路算法——Dijkstra(C++实现)
  • 最短路算法———Bellman_Ford算法(C++实现)
  • 最短路算法———SPFA算法(C++实现)
  • 最小生成树算法———prim算法(C++实现)
  • 最小生成树算法———Kruskal算法(C++实现)
  • 染色法判断二分图(C++实现)
  1. Linux部分(还在更新中):
  • Linux学习之初识Linux
  • Linux学习之命令行基础操作
  • Linux学习之基础命令(适合小白)
  • Linux学习之权限管理和用户管理

✨总结

“种一颗树最好的是十年前,其次就是现在”
所以,
“让我们一起努力吧,去奔赴更高更远的山海”
在这里插入图片描述
如果有错误❌,欢迎指正哟

如果觉得收获满满,可以动动小手,点点赞,支持一下哟

你可能感兴趣的:(Linux,linux,学习,运维,centos,ubuntu,静态库,动态库)