关于Unix静态库和动态库的分析

基本概念

库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。 例如:libhello.so libhello.a

为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。

ln -s libhello.so.1.0 libhello.so.1  ln -s libhello.so.1 libhello.so

1、使用库

当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。 然而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的 缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。

现在假设有一个叫hello的程序开发包,它提供一个静态库libhello.a 一个动态库libhello.so,一个头文件hello.h,头文件中提供sayhello()这个函数

/* hello.h */  void sayhello();

另外还有一些说明文档。

这一个典型的程序开发包结构 与动态库连接 linux默认的就是与动态库连接,下面这段程序testlib.c使用hello库中的sayhello()函数

/*testlib.c*/  #include "hello.h"  int main()  {      sayhello();      return 0;  }

使用如下命令进行编译

$gcc -c testlib.c -o testlib.o

用如下命令连接:

$gcc testlib.o -lhello -o testlib

    连接时要注意假设libhello.so 和libhello.a都在缺省的库搜索路径下/usr/lib下,如果在其它位置要加上-L参数。与静态库连接麻烦一些,主要是参数问题。还是上面的例 子:

$gcc testlib.o -o testlib -WI,-Bstatic -lhello

注:这个特别的”-WI,-Bstatic”参数,实际上是传给了连接器ld,指示它与静态库连接,如果系统中只有静态库当然就不需要这个参数了。如果要和多个库相连接,而每个库的连接方式不一样,比如上面的程序既要和 libhello进行静态连接,又要和libbye进行动态连接,其命令应为:

$gcc testlib.o -o testlib -WI,-Bstatic -lhello -WI,-Bdynamic -lbye

  注意:

         -WI,-Bstatic   -l库名                       //如果动态库和静态库同时存在,则加载静态库。

          -WI,Bdynamic   -l库名                       //如果动态库和静态库同时存在,则加载动态库。

2、动态库的路径问题                                            //指定库的路径的方法

为了让执行程序顺利找到动态库,有三种方法:

  1. 把库拷贝到/usr/lib和/lib目录下。
  2. 在LD_LIBRARY_PATH环境变量中加上库所在路径。例如动态库 libhello.so在/home/ting/lib目录下,以bash为例,使用命令: $export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ting/lib
  3. 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见。

注意:

也可以在使用gcc/g++编译程序时,让生成的可执行程序记住动态库的位置,方法:

gcc/g++    test.c   -o test   -WI,rlibpath   -llibname

这样编译出来的程序,自己就可以记住库的路径,就可以动态加载了。

3、查看库中的符号

有时候可能需要查看一个库中到底有哪些函数,nm工具可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多, 常见的有三种,一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所 谓的“弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。例如,假设开发者希望知道上文提到的hello库中是否引用了 printf():

$nm libhello.so | grep printf U

其中printf U表示符号printf被引用,但是并没有在函数内定义,由此可以推断,要正常使用hello库,必须有其它库支持,再使用ldd工具查看hello依赖于哪些库:

$ldd hello  libc.so.6=>/lib/libc.so.6(0x400la000)  /lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000)

从上面的结果可以继续查看printf最终在哪里被定义,有兴趣可以go on

可以使用    ar  -t   libname.a   来查看

4、生成库

第一步要把源代码编绎成目标代码。以下面的代码为例,生成上面用到的hello库:

/* hello.c */  #include "hello.h"  void sayhello()  {      printf("hello,world ");  }

用gcc编绎该文件,在编绎时可以使用任何合法的编绎参数,例如-g加入调试代码等:

$gcc -c hello.c -o hello.o

1.连接成静态库 连接成静态库使用ar工具,其实ar是archive的意思

$ar cqs libhello.a hello.o

2.连接成动态库 生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:

$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o

另外再建立两个符号连接:

$ln -s libhello.so.1.0 libhello.so.1  $ln -s libhello.so.1 libhello.so

这样一个libhello的动态连接库就生成了。最重要的是传gcc -shared 参数使其生成是动态库而不是普通执行程序。 -Wl 表示后面的参数也就是-soname,libhello.so.1直接传给连接器ld进行处理。实际上,每一个库都有一个soname,当连接器发现它正 在查找的程序库中有这样一个名称,连接器便会将soname嵌入连结中的二进制文件内,而不是它正在运行的实际文件名,在程序执行期间,程序会查找拥有 soname名字的文件,而不是库的文件名,换句话说,soname是库的区分标志。这样做的目的主要是允许系统中多个版本的库文件共存,习惯上在命名库 文件的时候通常与soname相同 libxxxx.so.major.minor 其中,xxxx是库的名字,major是主版本号,minor 是次版本号

转载于:https://www.cnblogs.com/wangfengju/archive/2013/01/28/6173294.html

gcc g++ Linux下动态库_静态库相关推荐

  1. Linux下制作和使用静态库和动态库

    写在前面: ldd + 可执行文件 可以查看可执行文件所依赖的库 概述: Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库.linux系统有几个重要的目录存放相应的函数库,如/lib ...

  2. Linux下ar指令与静态库转动态库方法

    1.Linux编译相关 1.1 编译 编译单个源文件 例如:main.c gcc main.c -o main ./main 编译多个源文件 例如:hello.h hello.c main.c gcc ...

  3. linux下编译自己的静态库时依赖其他的动态库,使用时出现“undefined reference to”

    对于我这个刚入IT行业不就得新手来说,在linux下链接库的时候总是会遇到各种各样奇葩的问题,最多的就是"undefined reference to"和"cannot ...

  4. Linux下动态库(.so)和静态库(.a)

     linux下有两种库:动态库和静态库(共享库) 二者的不同点在于代码被载入的时刻不同. 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大. 动态库(共享库)的代码在可执行程序运行时才 ...

  5. Linux下的动态库和静态库

    什么是库? 在 Linux 开发时,我们经常会看到一些形如 xxx.so 的名称出现,其中 so 是 Shared Object 的缩写,即可以共享的目标文件,也就是我们所称为的动态链接库,和在 Wi ...

  6. Linux下动态库和静态库制作与调用

    Linux下动态库和静态库制作与调用 1.动态库和静态库简介   静态库是指在应用中,有一些公共代码需要反复使用,就把这些代码编译为"库"文件:在链接步骤中,连接器将从库文件取得所 ...

  7. Linux下动态库(.so)和静态库(.a) 的区别

    linux下有两种库:动态库和静态库(共享库) 二者的不同点在于代码被载入的时刻不同. 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大. 动态库(共享库)的代码在可执行程序运行时才载入内 ...

  8. Linux下CMake简明教程(六)动态库和静态库的编译控制

    代码在git 有时只需要编译出动态库和静态库,然后等着让其它程序去使用.让我们看下这种情况该如何使用cmake.首先按照如下重新组织文件,只留下testFunc.h和TestFunc.c ├── CM ...

  9. GCC : 什么是编译?什么是静态库?什么是动态库?怎么生成?优先级?

    本文旨在让大家真正明白C程序如何运行.库文件的种类区别.如何生成.如何使用等! 一.简介: gcc 最初是 "GNU C Compiler" 的简称,只是当作一个 C 语言的编译器 ...

最新文章

  1. FPGA之道(15)组合逻辑与时序逻辑、同步逻辑与异步逻辑的概念
  2. WFP在包含fwpmu.h头的时候出错
  3. I Hate It(线段树基础)
  4. 【STM32】 keil软件工具--configuration详解(下)
  5. 跳板机连接数据库_跳板数据科学职业生涯回顾
  6. 后端技术:SpringBoot 中实现跨域的5种方式
  7. datatable 自定义搜索框 + 汉化
  8. 史上最全的女人坐月子注意事項
  9. Zookeeper单机安装(开启kerberos)
  10. 《黑客秘笈——渗透测试实用指南(第2版)》—第2章2.7节总结
  11. 我对前端技术更新的看法以及未来发展趋势预测
  12. 解决Could not load file or assembly CefSharp.Core.dll的问题
  13. windows无法安装iis信息服务器,windows server 2016 安装iis教程
  14. d盾web查杀 linux,D盾Web查杀
  15. cp105b linux 驱动,富士施乐 DocuPrint CP105b驱动
  16. 软件著作权申请需要哪些材料?
  17. Matlab论文插图绘制模板—柱状图(单组多色)
  18. 要求:弹出框接收字符串输入 输入aaabbbcccddd 输出3a3b3c3d
  19. 苹果手机用H5 audio标签无法自动播放音乐解决方法/html网页自动播放音乐
  20. 使用svg创建动态水印内容

热门文章

  1. 如何只导出mysql表结构_navicat如何只导出表结构
  2. 刷新DNS解析缓存+追踪+域名解析命令
  3. 如何在64位的Win10系统下安装.NET Framework 3.0
  4. 生成模型和判别模型_生成模型和判别模型简介
  5. 浓缩摘要_浓缩咖啡的收益递减
  6. garmin USB: linux USB host驱动
  7. 将ARM4412开发板配置成USB网卡,并且使用USB通过Ubuntu上网
  8. GDIPlus灰度化图像
  9. 低级键盘钩子 DLL
  10. 你是否做好了代码的备份?