静态库与动态库的简单说明

  一.静态库和动态库的简单介绍

  程序设计的模块化是人们一直在追求的目标,因为当一个系统十分复杂的时候,将系统模块化既可以并行开发,又可以增强程序的可用性,降低程序间的耦合度。在一个复杂的多模块系统中,

各个模块编译完成后,会生成各自的目标文件*.o,最后通过链接器将各个模块链接起来生成可执行文件。

库其实就是一个模块文件。人们为了将一些功能模块提供给他人使用,同时又不想将源代码直接分发给别人(也可能是不需要,毕竟库使用更方便,不用重新编译),就将功能模块做成库,

外部应用通过链接库来加载库的功能模块。比如glibc是GNU标准的C标准函数库。

库有静态和动态之分。静态库在编译时被链接进可执行文件中,动态库是在程序运行时链接。静态库的优点是使用方便,只要编译时链接成功,在程序运行时就不会有找不到库或者库错乱的

问题,但是这也造成了升级更新困难和内存空间浪费的问题。对于静态库来说,升级就必须重新编译应用程序链接静态库然后全部升级,而且如果多个应用程序都用到了同一个静态库,那么当多个

应用程序运行时,内存中就会有静态库的多个拷贝,十分浪费空间。因为这些原因,动态库应运而生。动态库是程序运行时才链接,所以在程序更新时,我们只需要更新动态库文件,重新启动应用

程序就会链接新库,而且当内存中已经有一个动态库的拷贝时,其他应用在运行时,如果需要链接库,会先从内存中查找库,找到后就直接链接该库,找不到再加载库到内存中,这保证了不会有同

一个库的多个拷贝在内存中占用空间。

  二.静态库和动态库的编译和链接 

  2.1 程序源码

  我们将会创建一个app,主要功能是输出“hello world”,具体实现在库libhello.a/libhello.so中实现。下面是各个文件的源代码:

      

  app源码

  #include<stdlib.h>

  #include<stdio.h>

  #include"hello.h"

  void main(void)

  {

  hello();

   hello();

  }

  

  库源码

  

  hello.c源码

  #include<stdlib.h>

  #include<stdio.h>

  void hello(void)

  {

  printf("\n======hello world======\n");

  }

  hello.h源码

  #ifndef HELLO_H

  #define HELLO_H

  void hello(void);

  #endif

  2.2.静态库的编译和链接

  

  第一步:生成目标文件

    # gcc -c hello.c

    生成目标文件hello.o

  第二步:编译生成静态链接库libhello.a

    # ar rcs libhello.a hello.o

  第三步:增加用于外部调用静态库函数的头文件hello.h

    hello.h头文件的作用是给外部调用库函数提供函数声明

  第四步:外部程序使用静态库

    在app.c中包含所用静态库函数声明的头文件hello.h

    生成app.o的目标文件

    #gcc -c app.c

    链接静态库libhello.a生成可执行文件app

    #gcc -o app app.o -L. -lhello

    执行app

    #./app

      ======hello world======

      ======hello world======

  2.3.动态库的生成

  同样是先生成目标文件hello.o,然后编译动态库文件libhello.so

  # gcc -shared -fPCI -o libhello.so hello.o

  # ls

  发现libhello.so已经生成了,然后我们开始生成可执行文件。这里动态库并没有链接。

  # gcc -o app app.o  -L. -lhello

  编译通过,执行app时出错

  #./app

  ./app: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

  程序运行时,找不到动态库。那为什么编译时能通过呢?因为编译时的-L指定了编译路径,所以编译能通过,但是在运行加载动态库时,会默认从/lib,/usr/lib路径下去找,而实际库不在该路径下,所以加载失败。

  

  解决的办法有三个:

  1.将库文件拷贝到默认的动态库路径/lib,/usr/lib,此为最简单,最快捷的方法

  2.程序编译时指定动态库路径,使用“-Wl,-rpath”。

    # gcc -o app app.o  -L. -lhello -Wl,-rpath=/mnt/hgfs/share/workspace/demo/LibraryDemo1

  注意:有的系统中可能是"-Wl,-rpath,/path/to/dir",使用时需要注意。还有就是我自己在使用时出现的小问题,提醒下大家,我开始总是写成-Wl,rpath=path,结果编译怎么都不过,总是提示找不打rpath=path这个文件或路径,后来才发现少写了个“-”,提醒大家需要认真看错误提示。

     3.就是更改/etc/ld.so.conf。查看/etc/ld.so.conf发现它包含了/etc/ld.so.conf.d目录下的所有*.conf。到/etc/ld.so.conf.d/目录下,

   新建一个*.conf,在里面加上动态库的路径(你也可以直接在其中某一个conf中增加一条,但是最好不要这么干,否则以后可能有未知的混乱)。

   此时运行app仍然失败,原因是系统查找动态库是通过查找/etc/ld.so.cache缓存,仅仅更改配置是不行的,还需要更新缓存。此时可以通过/sbin/ldconfig更新缓存。

   # /sbin/ldconfig

   有时候想知道动态库路径是否加入到缓存中,可以使用ldconfig指令

   # sudo /sbin/ldconfig -p |grep path

     在执行更新缓存后,可以查看到:

   # libhello.so (libc6) => /mnt/hgfs/share/workspace/demo/LibraryDemo1/libhello.so

    以上三种方法亲测可用。

时间: 2024-10-03 09:43:21

静态库与动态库的简单说明的相关文章

linux学习 建立静态库,动态库,写简单的makefile

建立静态库 建立四个文件 bin(可执行文件),lib(库),include(头文件),src(放源文件) 这里的起的库明为add 在src文件中执行 1)gcc -c add.c //编译add.c源文件生成add.o目标文件 2)ar crsv ../lib/ libadd.a add.o //对目标文件*.o进行归档,生成lib*.a, 把这个生成文件放在lib里 3)gcc -o main main.c -L(大些的爱偶,放库的路径)../lib   –l(小写的爱偶,库名为add) a

iOS 中的静态库与动态库,区别、制作和使用

如果我们有些功能要给别人用,但是又不想公开代码实现,比如高德地图.第三方登录分享等等,这时候我们就要打包成库了.库分静态库和动态库两种: 静态库:以.a 和 .framework为文件后缀名.动态库:以.tbd(之前叫.dylib) 和 .framework 为文件后缀名. 静态库与动态库的区别 静态库:链接时会被完整的复制到可执行文件中,被多次使用就有多份拷贝.动态库:链接时不复制,程序运行时由系统动态加载到内存,系统只加载一次,多个程序共用(如系统的UIKit.framework等),节省内

Linux使用静态库和动态库

Linux使用静态库和动态库 (一)库的概念 库是可以复用的代码,在一些大的项目中常常会用到库. 本质上说:库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 一般说库是说两种: 静态库:linux下.a文件.windows下.lib文件 动态库:linux下.so文件.windows下.dll文件 最近花了一些时间把linux下编译.链接等研究了一下,作为一个菜鸟记录并分享一蛤. (二)静态库与动态库 程序的编译运行要经过以下步骤: 1.源文件(.h .cpp等) 2.预编译 3.编

Linux下Gcc生成和使用静态库和动态库详解

参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主要是编译器.汇编器和连接器的不同),因此二者库的二进制是不兼容的. 本文仅限于介绍linux下的库. 1.2库的种类 linux下的库有两种:静态库和共享库(动态库). 二者的不同

静态库和动态库

简介 什么是库? 库是程序代码的集合,是共享程序代码的一种方式 根据源代码的公开情况,库可以分为2种类型 开源库 公开源代码,能看到具体实现 比如SDWebImage.AFNetworking 闭源库 不公开源代码,是经过编译后的二进制文件,看不到具体实现 主要分为:静态库.动态库 为什么制作闭源库 国内的企业,掌握有核心技术,同时是又希望更多的程序员来使用其技术,因此采用"闭源"的方式开发使用 例如:百度地图,友盟,JPush等 在企业开发中,一些核心技术或者常用框架,出于安全性和稳

【转】Linux下gcc生成和使用静态库和动态库详解

一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主要是编译器.汇编器和连接器的不同),因此二者的库的二进制是不兼容的. 本文仅限于介绍linux下的库. 1.2 库的种类 linux下的库有两种:静态库和共享库(动态库). 二者的不同点在于代码被载入的时刻不同. 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大. 共享库的代码是在可

C++静态库与动态库(比较透彻)

这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一本书<程序员的自我修养——链接.装载与库>. 什么是库 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.库有两种:静态库(.a..lib)和动态库(.so..

(转)HelloWorld CMake CMake中构建静态库与动态库及其使用

继续完善Hello World,建立它的共享库, 包括静态库和动态库. 本节的任务: 1,建立一个静态库和动态库,提供HelloFunc函数供其他程序编程使用,HelloFunc 向终端输出Hello World字符串. 2,安装头文件与共享库. 3, 编写一个程序使用创建的共享库(静态库和动态库). cd /home/ccj/CMakeDemo mkdir t3   cd /backup/cmake/t3 mkdir lib   在t3目录下建立CMakeLists.txt,内容如下: PRO

Linux 如何生成静态库和动态库

1.引言 1.linux下的库 静态库和共享库(动态库),二者的不同点在于代码被载入的时刻不同. 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大. 共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小. 2.库存在的意义 库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议. 现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 共享库的好处是,不同的应用程序如果调用相同的库,那么