`
aspnetwinform
  • 浏览: 89916 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
社区版块
存档分类
最新评论

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

 
阅读更多

linux下有两种库:动态库和静态库(共享库)

二者的不同点在于代码被载入的时刻不同。

静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大。

动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。

不同的应用程序如果调用相同的库,那么在内存中只需要有一份该动态库(共享库)的实例。

静态库和动态库的最大区别,静态情况下,把库直接加载到程序中,而动态库链接的时候,它只是保留接口,将动态库与程序代码独立,这样就可以提高代码的可复用度,和降低程序的耦合度。

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库

动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在

一 静态库

这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

静态库的代码在编译时链接到应用程序中,因此编译时库文件必须存在,并且需要通过“-L”参数传递给编译器,应用程序在开始执行时,库函数代码将随程序一起调入进程内存段直到进程结束,其执行过程不需要原静态库存在。

在UNIX中,使用ar命令创建或者操作静态库

ar archivefile objfile

archivefile:archivefile是静态库的名称

objfile:objfile是已.o为扩展名的中间目标文件名,可以多个并列

参数 意义

-r 将objfile文件插入静态库尾或者替换静态库中同名文件

-x 从静态库文件中抽取文件objfile

-t 打印静态库的成员文件列表

-d 从静态库中删除文件objfile

-s 重置静态库文件索引

-v创建文件冗余信息

-c 创建静态库文件

example:

  1. /******************hello.h**************/
  2. voidhello(void);
  1. /******************hello.cpp**************/
  2. #include<iostream>
  3. #include"hello.h"
  4. usingnamespacestd;
  5. voidhello(void)
  6. {
  7. cout<<"Hello"<<endl;
  8. }
  1. /******************main.cpp**************/
  2. #include"hello.h"
  3. intmain(intargc,char*argv[])
  4. {
  5. hello();
  6. return0;
  7. }


1.编译成静态库

无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。

hc@linux-v07j:~/weiming/tt> g++ -o hello.o -c hello.cpp

hc@linux-v07j:~/weiming/tt> ar cqs libHello.a hello.o

hc@linux-v07j:~/weiming/tt> ls
hello.cpp hello.h hello.olibHello.a main.cpp

2.链接

hc@linux-v07j:~/weiming/tt> g++ main.cpp libHello.a -o Out1 (g++ -o aOut main.cpp ./libHello.a 或者 g++ -o aOut main.cpp -L./ -lHello)

hc@linux-v07j:~/weiming/tt> ls
hello.cpp hello.h hello.o libHello.a main.cppOut1

hc@linux-v07j:~/weiming/tt> ldd Out1
linux-gate.so.1 => (0xffffe000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e36000)
libm.so.6 => /lib/libm.so.6 (0xb7e11000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7e06000)
libc.so.6 => /lib/libc.so.6 (0xb7ce3000)
/lib/ld-linux.so.2 (0xb7f1b000)

二: 动态库

这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便

不同的UNIX系统,链接动态库方法,实现细节不一样

编译PIC型.o中间文件的方法一般是采用C语言编译器的-KPIC或者-fpic选项,有的UNIX版本C语言编译器默认带上了PIC标准.创建最终动态库的方法一般采用C语言编译器的-G或者-shared选项,或者直接使用工具ld创建。

最主要的是GCC命令行的一个选项:
-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
-L.:表示要连接的库在当前目录中
-ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

这里分别将源文件d1.c和d2.c编译为动态库d1.so和d2.so.

  1. /************d1.h***************/
  2. voidprint();
  1. /***************d1.cpp*******************/
  2. #include<iostream>
  3. #include"d1.h"
  4. usingnamespacestd
  5. intp=1;
  6. voidprint()
  7. {
  8. cout<<p<<endl;
  9. }
  1. /************d2.h***************/
  2. voidprint();
  1. /***************d2.cpp*******************/
  2. #include<iostream>
  3. #include"d2.h"
  4. usingnamespacestd;
  5. intp=2;
  6. voidprint()
  7. {
  8. cout<<p<<endl;
  9. }

LINUX和其他gcc编译器

g++ -fpic -c d1.cpp d2.cpp /*编译为.o为扩展名的中间目标文件d1.o,d2.o*/

g++ -shared -o libd1.so d1.o /*根据中间目标文件d1.o创建动态库文件d1.so*/

g++ -shared -o libd2.so d2.o /*根据中间目标文件d2.o创建动态库文件d2.so*/

或者直接一步到位

g++ -O -fpic -shared -o libd1.so d1.cpp

g++ -O -fpic -shared -o libd2.so d2.cpp

某些版本的gcc上也可以使用-G替换-shared选项

调用动态库

隐身调用动态库

  1. /**************main.cpp*********************/
  2. voidprint();//或者用#include"d1.h"(#include"d2.h")替换
  3. intmain(intargc,char*argv[])
  4. {
  5. print();
  6. }

#cp ./libd1.so libd.so (cp ./libd2.so libd.so )

#g++ -o dOut main.cpp ./libd.so (或者g++ -o dOut main.cpp -L./ -ld)

hc@linux-v07j:~/weiming/tt/dd> ldd dOut
linux-gate.so.1 => (0xffffe000)
libd.so => ./libd.so (0xb7f0f000) //这个动态库文件比静态编译多的
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e2b000)
libm.so.6 => /lib/libm.so.6 (0xb7e06000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7dfa000)
libc.so.6 => /lib/libc.so.6 (0xb7cd8000)
/lib/ld-linux.so.2 (0xb7f12000)

在上例中,动态库libd.so与执行程序在同一目录下,如果将libd.so移走再执行程序,程序将不能正常执行。

当需要载入动态库代码时,UNIX会按照某种路径查找动态库

通知UNIX系统动态库的正确位置有如下两种方法.,

1)带编译路径

#g++ -o dOut main.cpp ./libd.so (或者g++ -o dOut main.cpp -L./ -ld)

当执行程序时,程序会自动在当前路径下操作动态库libd.so

2)更改环境变量

#LD_LIBPARY_PATH=./

#export LD_LIBPARY_PATH

不同的UNIX所依赖的动态库查找路径环境变量名称各不相同

UNIX版本 动态库查找路径环境变量

AIX LIB_PATH

LINUX LD_LIBPARY_PATH

HP_UNIX PAHT

SCO UNIX LD_LIBPARY_PAHT

动态链接库取代静态库的好处之一就是可以随时升级库的内容。

当动态库被接口完全相同的库文件取代后,可执行程序能迅速的切换到新动态库中代码,省去了编译的麻烦。

例如将libd2.so换成libd.so

显示调用动态库

显示调用动态库,编译时无需库文件,执行时动态可存储于任意位置,库里共享对象必须先申请后使用,不同动态库版本,只要其共享对象接口相同,就可以直接动态加载。

  1. //打开动态库
  2. #include<dlfcn.h>
  3. void*dlopen(constchar*pathname,intmode);
  4. //获取动态库对象地址
  5. include<dlfcn.h>
  6. void*dlsym(void*handle,constchar*name);
  7. //错误检测
  8. include<dlfcn.h>
  9. char*dlerror(vid);
  10. //关闭动态库
  11. include<dlfcn.h>
  12. intdlclose(void*handle);

动态库的加载或多或少会占用一定的系统资源,比如内存等。因此当不需要或者一段时间内不需要共享动态库时就要卸载之。函数dlclose关闭参数handle所指向的动态库,卸载其所占的内存等资源,此调用后参数handle无效。

实际上,由于动态库可能同时被多个进程共享,当一个进程指向dlclose时,资源并不马上被卸载,只有当全部进程都宣布关闭动态库后,操作系统才开始回收动态库资源。

总结:

编译静态库时先使用-c选项,再利用ar工具产生.编译动态库的方式依不同版本的UNXI而定。隐式调用动态库与静态库的用法相一致,而显示调用动态库则需要借助动态加载共享库函数族。

隐式调用动态库和静态库使用方法一致,使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?

通过测试可以发现,当静态库和动态库同名时, gcc命令将优先使用动态库.为了确保使用的是静态库, 编译时可以加上 -static 选项,因此多第三方程序为了确保在没有相应动态库时运行正常,喜欢在编译最后应用程序时加入-static


来自:http://blog.csdn.net/felixit0120/article/details/7652907


分享到:
评论

相关推荐

    [转]在Linux中创建静态库.a和动态库.so

    在Linux系统中,开发软件时经常需要使用到库文件,它们分为静态库(.a)和动态库(.so)。本文将详细介绍如何在Linux环境中创建这两种类型的库,并探讨它们的区别和使用场景。 首先,让我们理解静态库和动态库的...

    动态链接库及静态链接库(windows下的.dll .lib和linux下的.so .a).docx

    动态链接库及静态链接库(Windows下的.dll .lib和Linux下的.so .a) 动态链接库和静态链接库是两种不同的库文件类型,它们在编译和链接过程中扮演着重要的角色。下面我们将详细探讨这两种库文件的特点和使用方法。 ...

    Linux下g++编译与使用静态库和动态库的方法

    在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库(*.a)与动态库(*.so)的生成...

    linux 动态库静态库

    通过压缩包中的"linux动态库及静态库的创建和使用"文件,你可以找到更具体的实践教程和示例代码,包括如何创建、链接和使用这两种类型的库,以及解决可能出现的问题。这些资料将帮助你深入理解和掌握Linux环境下的...

    linux下g++编译与使用静态库和动态库

    静态库(*.a)和动态库(*.so)是 Linux 下两种常用的库文件类型,了解它们的生成和使用方法是非常必要的。本文将详细介绍 Linux 下生成和使用静态库和动态库的方法。 静态库(*.a) 静态库是一种库文件类型,它将...

    linux静态库和动态库

    ### Linux静态库与动态库详解 #### 一、引言 在Linux环境下,库是一种重要的软件组件,用于封装一组相关的函数或数据结构,以便于在不同的应用程序之间共享代码。库通常分为两大类:静态库(static libraries)和...

    Linux动态链接库.so文件的创建与使用

    总的来说,Linux动态链接库`.so`文件的创建和使用是系统编程中的关键技能,掌握这一技术有助于优化程序性能,实现模块化设计,并有效地管理系统资源。在实际开发中,了解如何创建、管理及使用动态链接库对于提升软件...

    linux下编译.so库文件

    在Linux系统中,库文件分为静态库和动态库两大类,它们分别以`.a`和`.so`作为文件扩展名,服务于不同的编译链接需求。 - **静态库**:通常包含多个`.o`目标文件的集合,用于在编译时链接到应用程序中。这意味着在...

    boost库1.68版本Linux下编译的动态库和静态库

    这将编译动态库(`.so`)和静态库(`.a`),并安装到指定的路径。 5. **测试与验证**:编译完成后,为了确保库的可用性,可以运行Boost的测试套件,用`bjam test`执行所有测试案例。如果所有测试都通过,那么说明库...

    Linux动态库.txt

    ### Linux动态库详解 #### 一、概述 Linux 动态库是操作系统中不可或缺的一部分,它们使得多个程序能够共享相同的代码段,进而减小程序体积、提高资源利用率。本文将详细介绍 Linux 动态库的基本概念、如何管理和...

    Linux编译动态库和静态库

    在Linux系统中,开发软件时常会遇到需要创建和使用动态库(.so)与静态库(.a)的情况。动态库允许多个程序共享同一份代码,节省内存资源,而静态库则将库代码直接编译进目标程序,不依赖外部环境。本篇将详细介绍在...

    opencv4.4.0交叉编译好的动态库和静态库.rar

    动态库(.so文件)与静态库(.a文件)是两种常见的库文件类型。动态库在程序运行时被加载到内存中,多个程序可以共享同一份库,节省内存资源,但需要目标系统已安装相应的库。静态库则在编译时会将库代码合并到可...

    lua-5.2.0静态库+动态库.zip

    在这个“lua-5.2.0静态库+动态库.zip”压缩包中,包含的是Lua 5.2.0版本的源代码,以及编译后的静态库和动态库文件。这些库文件对于开发者来说是至关重要的,因为它们允许在C/C++项目中集成Lua功能。 首先,我们来...

    libc.so.6 libc.so.6

    《深入理解Linux动态链接库:以libc.so.6为例》 在Linux系统中,`libc.so.6`是一个至关重要的动态链接库,全称为“GNU C Library”,它提供了大量用于程序开发的基础函数,如字符串处理、内存管理、I/O操作等。这个...

    android串口程序 含有串口静态库.so文件

    使用静态库的好处是避免了运行时找不到动态库的问题,同时减少了应用程序的体积。 Android串口通信主要涉及以下几个方面: 1. **权限设置**:在AndroidManifest.xml文件中,需要添加`&lt;uses-permission&gt;`标签,如`...

    openssl 静态库 libcrypto.a libssl.a

    在本文中,我们将深入探讨如何在 Linux(尤其是 CentOS 7)环境下编译并创建 OpenSSL 的静态库 `libcrypto.a` 和 `libssl.a`。 首先,让我们理解什么是静态库。静态库是编译时链接到可执行文件中的库文件,它们将库...

    QNX系统中添加自己编译的.so库.zip_QNX .so文件_SO打包_qnx文件_qnx系统g++编译_so库

    与静态库(.a文件)不同,动态库不会被编译进可执行文件,而是运行时按需加载,这有助于减少程序的内存占用和启动时间。 在QNX系统中,使用g++编译器来创建.so库。以下是基本步骤: 1. **编写源代码**:使用C++...

    linux下用gcc生成静态库和动态库.doc

    在Linux环境下,使用GCC(GNU Compiler Collection)生成静态库和动态库是开发过程中的常见操作。静态库和动态库在程序构建和运行时各有特点,理解它们的工作原理和创建方法对于软件开发至关重要。 首先,静态库在...

    Linux静态库和动态库

    **命名规范**:Linux中,静态库通常命名为`libXXXX.a`,而动态库则为`libXXXX.so.major.minor`,其中`XXXX`代表库的名称,`major`和`minor`分别表示主版本号和次版本号。 **库的查找与依赖**:通过`ldd`命令可以...

Global site tag (gtag.js) - Google Analytics