1.动态库与静态库简介

在实际的软件开发中,为了方便使用一些被重复调用的公共代码,我们经常将这些公共的函数编译成动态库或静态库。我们知道程序一般要经过预处理、编译、汇编和链接这几个步骤才能变成可执行的文件,程序的静态库是在做链接的步骤时,通过连接器将静态库的代码copy到可执行文件中,目标文件包含所有的静态库代码。因此目标文件在执行的时候不需要静态库的支持,但是在当静态库改变时则需要重启编译可执行文件。在Linux中,一般静态库是以 XXX.a命名。而动态库不会被编译到目标代码中,而是在执行到库的相关函数时才会去调用。因此当动态库函数改变时,只要保证动态库所存放的路径不变,我们将新的动态库覆盖旧的动态库就OK了, 在Linux中,动态库一般以XXX.so命名。

2.动态库与静态库的实现

2.1 静态库在可以通过gcc编译源代码文件而得到,在Linux中我们可以通过file xxx.a查看其文件属性,用ar -t xxx.a 查看这个静态库包含的目标,如下所示:

 /lib64> file libapparmor.a
libapparmor.a: current ar archive /lib64> ar -t libapparmor.a
grammar.o
libaalogparse.o
kernel_interface.o
scanner.o

2.2 静态库目前在Linux中很少见了,更多用的是动态库, 动态库可以通过 “gcc -shared -fPIC XXX.so xxx.o”编译而成。

-shared该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件。

-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。

我们可以用两个方式来查看该目标文件所引用的动态库(ldd & readelf):

ELF 文件包含了共享库文件信息,我们可以注意到ldd列出来的比readelf列出来的库文件多,这是因为ldd列出来的是实际运行加载的库文件, 而readelf列出来的是编译时链接的库文件。

 ldd /usr/bin/ls
linux-vdso.so. (0x00007ffe655c0000)
libselinux.so. => /lib64/libselinux.so. (0x00007fdeeee47000)
libcap.so. => /lib64/libcap.so. (0x00007fdeeec42000)
libc.so. => /lib64/libc.so. (0x00007fdeee89e000)
libpcre.so. => /usr/lib64/libpcre.so. (0x00007fdeee62f000)
libdl.so. => /lib64/libdl.so. (0x00007fdeee42b000)
/lib64/ld-linux-x86-.so. (0x0000556694a1a000)
libpthread.so. => /lib64/libpthread.so. (0x00007fdeee20d000) readelf -d /usr/bin/ls Dynamic section at offset 0x1cd98 contains entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libselinux.so.]
0x0000000000000001 (NEEDED) Shared library: [libcap.so.]
0x0000000000000001 (NEEDED) Shared library: [libc.so.]
0x000000000000000c (INIT) 0x402770
0x000000000000000d (FINI) 0x4141ac
0x0000000000000019 (INIT_ARRAY) 0x61c368
0x000000000000001b (INIT_ARRAYSZ) (bytes)
0x000000000000001a (FINI_ARRAY) 0x61c370
0x000000000000001c (FINI_ARRAYSZ) (bytes)
0x0000000000000004 (HASH) 0x400298
0x000000006ffffef5 (GNU_HASH) 0x4006e0
0x0000000000000005 (STRTAB) 0x401468
0x0000000000000006 (SYMTAB) 0x400748
0x000000000000000a (STRSZ) (bytes)
0x000000000000000b (SYMENT) (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x61d000
0x0000000000000002 (PLTRELSZ) (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x401cf0
0x0000000000000007 (RELA) 0x401c00
0x0000000000000008 (RELASZ) (bytes)
0x0000000000000009 (RELAENT) (bytes)
0x000000006ffffffe (VERNEED) 0x401b90
0x000000006fffffff (VERNEEDNUM)
0x000000006ffffff0 (VERSYM) 0x401a72
0x0000000000000000 (NULL) 0x0

动态库的加载有两个,一种是按照库的路径搜索并加载,加载的优先级如下:

  1、RUNPATH 优先级最高    
  2、RPATH   其次               编译时指定
  3、LD_LIBRARY_PATH    环境变量指定
  4、/etc/ld.so.cache            可以通过ldconfig修改
  5、/usr/lib/ /lib/                  

另一种加载方式是依赖于Linux提供的API 来完成, API提供的函数声明,包含头文件:dlfcn.h.

关于动态库和静态库就说这么多了,水平有限,错误请指正,谢谢!

Linux的动态库与静态库的更多相关文章

  1. Linux中的动态库和静态库(.a/.la/.so/.o)

    Linux中的动态库和静态库(.a/.la/.so/.o) Linux中的动态库和静态库(.a/.la/.so/.o) C/C++程序编译的过程 .o文件(目标文件) 创建atoi.o 使用atoi. ...

  2. Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf 动态库的后缀为*.so 静态库的后缀为 libxxx.a ldconfig 目录名

    Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf  动态库的后缀为*.so  静态库的后缀为 libxxx.a   ldconfig   目录名 转载自:http://b ...

  3. Linux系统中“动态库”和“静态库”那点事儿【转】

    转自:http://blog.chinaunix.net/uid-23069658-id-3142046.html 今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻. ...

  4. 技巧:Linux 动态库与静态库制作及使用详解

    技巧:Linux 动态库与静态库制作及使用详解 标准库的三种连接方式及静态库制作与使用方法 Linux 应用开发通常要考虑三个问题,即:1)在 Linux 应用程序开发过程中遇到过标准库链接在不同 L ...

  5. Linux系统中“动态库”和“静态库”那点事儿

    摘自http://blog.chinaunix.net/uid-23069658-id-3142046.html 今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻.在 ...

  6. linux动态库与静态库混合连接

      1, 在应用程序需要连接外部库的情况下,linux默认对库的连接是使用动态库,在找不到动态库的情况下再选择静态库.使用方式为: gcc test.cpp -L. -ltestlib 如果当前目录有 ...

  7. Linux环境编译动态库和静态库总结

    对Linux环境动态库和静态库的一些基础知识做一些总结, 首先总结静态库的编译步骤. 1 先基于.cpp或者.c文件生成对应的.o文件 2将几个.o文件 使用ar -cr命令 生成libname.a文 ...

  8. Linux下编译、使用静态库和动态库 自己测过的

    每个程序实质上都会链接到一个或者多个的库.比如使用C函数的程序会链接到C运行时库,GUI程序会链接到窗口库等等.无论哪种情况,你都会要决定是链接到静态库(static libary)还是动态库(dyn ...

  9. 自己在linux上编译、链接、动态库和静态库的学习笔记

    在平常的项目中,我们都是使用公司要求的makefile.makedebug一类的文件,因此,在编译.链接.生成和链接动态库与静态库的时候,我们只是简单的使用一些已经设置的变量,只是简单的修改.添加一些 ...

随机推荐

  1. TCP三次握手及其背后的缺陷

    概述 总结一下TCP中3次握手过程,以及其原生的缺陷 引起的SYN Flood的介绍 [1]TCP三次握手 [2]SYN Flood 1.TCP连接建立--三次握手 几个概念: [1]seq:序号,占 ...

  2. C++ Primer 有感(异常处理)(四)

    查看普通函数的声明的时候,不可能知道该函数会抛出什么异常,但是在捕获异常的时候要知道一个函数会抛出什么样的异常,以便捕获异常. 异常说明:指定,如果函数抛出异常,抛出的异常将是包含在该说明中的一种,或 ...

  3. Linux C 下的大文件操作

    这里说的大文件指大小超过4G的文件. 在32位环境下,linux默认打开.读.写超过4G的文件会返回错误.定义如下宏可以突破这个限制,对read/write和fread/fwrite同时有效. 注意它 ...

  4. mongoDB常见的查询索引(三)

    1. _id索引     _id索引是绝大多数集合默认建立的索引     对于每个插入的数据,MongoDB会自动生成一条唯一的_id字段. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  5. MyBatis - 介绍、简单入门程序

    JDBC编程中的问题     1. 将SQL语句硬编码到Java代码,不利于系统维护.         设想如何解决:将SQL单独抽取出来,在配置文件(xml方式.properties文件)进行配置. ...

  6. C++异常处理基本思想

    传统错误处理机制 通过函数返回值来处理错误. 异常处理的基本思想 1)C++的异常处理机制使得异常的引发和异常的处理不必在同一个函数中,这样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理. ...

  7. (视频) 《快速创建网站》 3.2 WordPress多站点及Azure在线编辑器 - 扔掉你的ftp工具吧,修改代码全部云端搞定

    本文是<快速创建网站>系列的第6篇,如果你还没有看过之前的内容,建议你点击以下目录中的章节先阅读其他内容再回到本文. 1. 网站管理平台WordPress和云计算平台Azure简介 (6分 ...

  8. 《java入门第一季》之面向对象(重头戏继承来了)

    java特性封装.继承.多态.之前对封装做了简单描述(见http://blog.csdn.net/qq_32059827/article/details/51312116),今天分析另一个特性继承性: ...

  9. 关于SMALI语法

    dalvik字节码有两种类型,原始类型和引用类型.对象和数组是引用类型,其它都是原始类型.V  void,只能用于返回值类型Z  booleanB  byteS  shortC  charI  int ...

  10. 网站开发进阶(二十)JS中window.alert()与alert()的区别

    JS中window.alert()与alert()的区别 前言 alert与window.alert没什么区别,如果有人觉得有区别,那就来解释一下:所有以window.开始的语句,都可以直接把wind ...