专栏首页Zaqdt_ACMLinux的静态库和共享库详解及实例

Linux的静态库和共享库详解及实例

       库的本质上是一个可执行的二进制文件,但是它并不能独立的执行。简单的来说,就相当于一个仓库,把你已经写好的功能函数放到库中,然后后续需要时通过正确的接口去使用相应的功能,当然可以把库分享给别人也很方便。在Linux下分为静态库和共享库(也叫动态库),当然Windows下也有静态库(.lib)和动态库(.dll),这里主要是讲解Linux下的静态库和共享库,以及它们的简单实现。

       在Linux中静态库以.a为后缀,首先静态库的实现是在文件编译后的链接过程中就被载入到了程序中,那么后续的程序的运行使用就不会再依赖库,那么弊端就是将静态库载入到程序中会导致程序的体积变大,而且如果静态库后续进行了更新,那么程序就需要重新编译会有些麻烦。

       而共享库以.so为后缀,它的实现方式是在链接的过程中不会将库载入到程序中,而是生成一个记录表,当程序运行的时候再去通过记录表去链接共享库,那么这个的好处就是程序的体积小,而且当有不同的程序公用一个库的时候,就只需要链接这一个库就够了,并且共享库后续的更新依据其版本号也比较方便,但是运行程序时需要依赖共享库。

       对于两种库的使用,需要结合实际情况来选择使用。下面用加减乘除的例子来简单的实现一下两个库的创建。我所用的系统是Ubuntu18.04 server版,首先我先把文件夹和一些文件都提前创建好了。

       首先我们先将这些函数文件编译为.o文件,需要加上-fPIC参数,表示让生成的.o文件与路径无关,这一点主要是用于共享库的操作,单纯只用静态库的话可以不加。

静态库

       对于静态库的创建用ar命令:ar  rcs  静态库名.a  *.o,然后我们就得到了一个.a的静态库,然后我将其放到了lib文件夹下。

       然后我们将其链接成可执行文件观察一下效果,因为所有的参数都是4 2,所以最终的结果就是6 2 8 2。 

共享库

对于一个共享库来说,它可以有三个名字,虽然这不是必须的,但是对于有后续的版本的维护或者更新来说,最好是规范的使用这三个名字,可以极大的方便我们去维护和更新共享库。共享库包括realname soname linkname三个名字,realname的结构如下

       libXXXX.so是一般不变的,后面的版本号可能会随着维护和更新从而做出改变,一般来说发行版本号的增加是修改了一些bug或者做了一些优化,调用时不会有其他的影响。次版本号是向下兼容的,也就是说libxxx.so.1.2.0是对libxxx.so.1.1.0兼容,也就是说在原有的接口不变的情况下添加了一些新的特性,提供了新的功能。主版本号的增加就说明了它是不兼容的,需要重新编译链接。通常我们都会将soname和linkname分别与realname建立软连接,那么链接soname和linkname实际上就是链接到了realname。那么libXXXX.so.X就是soname,libXXXX.so是linkname。

       下面就还是以上面的例子来创建一个共享库。首先我们要对.cpp文件进行编译,那么-fPIC这个命令此时就不能少,表示编译的文件与路径无关,也就是说生成的文件都是相对路径,而不是绝对路径,如果使用绝对路径,那么在多个进程共享使用这个库的时候,会根据这个代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy,那么就相当于每个进程都维护了一个自己的.so的副本,因此就做不到共享了。那么生成的文件是路径无关的,那么不管被加载到内存的任何位置,程序都可以正确的执行。

       我们先在lib下建立一个linkname的软链接,然后再去编译main.cpp和共享库,其中-L参数后面跟你的共享库的所在目录,-l后面跟库的名称,因为我的库是libmytest.so,所以我的库的名称就是mytest,需要注意的是这里要有linkname的软链接才可以用-l参数,否则会报cannot find错误(原因就是有.so.文件,但是没有.so文件)。

       这里虽然编译成功了,但是其实还是无法运行test,是因为系统找不到这个共享库的路径,可以通过ldd test来查看可执行文件的动态链接库

       可以清晰的看出来找不到我们要链接的动态库,所以我们要去修改一下etc/ld.so.conf的配置文件,在最后一行加上你的库所在的目录就好了。然后通过ldconfig -v来更新系统中的动态链接库,然后我们就可以发现soname就有动态库的目录了,而且在lib中也生成了soname的软链接文件。

        然后就可以运行我们的可执行文件了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Educational Codeforces Round 63 (Rated for Div. 2) D. Beautiful Array(dp)

    题目链接:https://codeforces.com/contest/1155/problem/D

    Ch_Zaqdt
  • HDU 1171 Big Event in HDU(01背包)

           题意在代码注释中有,思路就是先记录所有价值的总和sum,既然要求两个学院分得的器材价值尽量接近,那么取总和的一半ans,让其中一个学院尽量接近an...

    Ch_Zaqdt
  • HDU 1285 确定比赛名次(拓扑排序&&优先队列优化)

       拓扑排序最主要的就是依靠入度进行排序,至于入度是什么,这是一个传送门 点开看看就好了。以这道题为例,裁判不知道队伍的成绩,只知道胜负,自然获胜的越多就...

    Ch_Zaqdt
  • Mac全栈开发-编辑器

    为了方便在终端直接用SublimeText打开我们的项目,为此可以设置一下Subl来软链接到实际的路径。

    用户1065635
  • Django 1.10中文文档-第一个应用Part6-静态文件

    目录[-] 本教程上接Part5 。前面已经建立一个网页投票应用并且测试通过,现在主要讲述如何添加样式表和图片。 除由服务器生成的HTML文件外,网页应用一...

    jhao104
  • How myTask application is loaded in CreateFromAccount scenario

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    Jerry Wang
  • GCC/G++选项 -Wl,-Bstatic和-Wl,-Bdynamic

    默认情况下,GCC/G++链接时优先链接动态库,如果没有动态库,则链接相应的静态库。同时,GCC/G++也提供了链接选项 -Wl,-Bstatic 和 -Wl,...

    用户1117071
  • Java程序员跳槽应该学习哪些技术?

    工作1-5年,当我们向老板提出加薪的时候,或者跳槽去“捡”offer的时候,我们底气够吗?

    java架构师
  • 具有一到五年开发经验的程序员该如何提升自己?

    敢不敢不给涨薪就“挥一挥衣袖,不带走一个bug”?是不是提出要求后你的主管、经理立刻

    zhisheng
  • 有经验的程序员应该如何提升自己

    工作1-5年,当我们向老板提出加薪的时候,或者跳槽去“捡”offer的时候,我们底气够吗? 敢不敢不给涨薪,就“挥一挥衣袖,不带走一个bug”?是不是提出要求后...

    架构师小秘圈

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动