基本概念
库有动态与静态两种,动态通常用.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.o1.连接成静态库 连接成静态库使用ar工具,其实ar是archive的意思
$ar cqs libhello.a hello.o2.连接成动态库 生成动态库用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 是次版本号
总结
通过对LINUX库工作的分析,我们已经可以理解程序运行时如何去别的地方寻找“库”。
附上针对这个工程的Makefile:
# xiejingquan@gmail.com # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/C/lib BIN_DIR=bin LIB_DIR=lib INC_DIR=inc SRC_DIR=src BIN=${BIN_DIR}/testlib LIB=${LIB_DIR}/libhello.a ${LIB_DIR}/libhello.so CC=gcc AR=ar DOC=doxygen CFLAGS=-g -Wall -c -Iinc LFLAGS=-lhello -L${LIB_DIR} -o ARFLAGS=cqs SOFLAGS=-shared -Wl,-soname, all: ${BIN} lib: ${LIB} run: all @./bin/testlib clean: rm -f ${BIN_DIR}/* ${LIB_DIR}/* ${BIN_DIR}/testlib: ${LIB_DIR}/testlib.o ${LIB} ${CC} $< ${LFLAGS} $@ ${LIB_DIR}/testlib.o: ${SRC_DIR}/testlib.c ${INC_DIR}/hello.h ${CC} ${CFLAGS} $< -o $@ ${LIB_DIR}/libhello.a: ${LIB_DIR}/hello.o ${AR} ${ARFLAGS} $@ $< ${LIB_DIR}/libhello.so: ${LIB_DIR}/hello.o ${CC} ${SOFLAGS}libhello.so.1 -o ${LIB_DIR}/libhello.so.1.0 ${LIB_DIR}/hello.o ln -s ${LIB_DIR}/libhello.so.1.0 ${LIB_DIR}/libhello.so.1 ln -s ${LIB_DIR}/libhello.so.1 ${LIB_DIR}/libhello.so ${LIB_DIR}/hello.o: ${SRC_DIR}/hello.c ${INC_DIR}/hello.h ${CC} ${CFLAGS} $< -o $@附上文件的目录结构:
|– bin
| `– testlib
|– doc
|– inc
| `– hello.h
|– lib
| |– hello.o
| |– libhello.a
| |– libhello.so -> lib/libhello.so.1
| |– libhello.so.1 -> lib/libhello.so.1.0
| |– libhello.so.1.0
| `– testlib.o
|– src
| |– hello.c
| `– testlib.c
--------------------------------------------------------------------------------
分享到:
相关推荐
### Linux静态库与动态库详解 #### 一、引言 在Linux环境下,库是一种重要的软件组件,用于封装一组相关的函数或数据结构,以便于在不同的应用程序之间共享代码。库通常分为两大类:静态库(static libraries)和...
这将编译动态库(`.so`)和静态库(`.a`),并安装到指定的路径。 5. **测试与验证**:编译完成后,为了确保库的可用性,可以运行Boost的测试套件,用`bjam test`执行所有测试案例。如果所有测试都通过,那么说明库...
本篇将详细介绍在Linux环境下如何编译动态库和静态库。 首先,我们来看动态库的生成过程。动态库的编译通常分为两个步骤: 1. 编译源文件为`.o`对象文件: 使用`cpp`或`gcc`命令,加上`-c`选项来编译源代码,并...
### 举例分析Linux动态库和静态库 #### 静态库与动态库的基本概念 在Linux环境下,静态库和动态库是两种常见的链接库形式,它们分别在编译和运行阶段发挥着不同的作用。 **静态库**在程序编译过程中会被链接到...
默认编译是静态库,但考虑到 linux 上动态库使用较多,所以使用 -DBUILD_SHARED_LIBS=ON 参数编译为动态库。 在 centos 7 下使用 gcc 4.8.5 + cmake 3.16.9 编译,包含 bin, include, lib, lib64, share 五个目录,...
### Linux下Gcc生成和使用静态库和动态库详解 #### 一、基本概念 **1.1 什么是库** 库本质上是一种可执行代码的二进制形式,它可以被操作系统载入内存执行。无论是Windows还是Linux平台,都广泛地使用着库。然而...
在Linux操作系统中,库文件是...总之,理解Linux下的静态库和动态库以及如何生成和使用它们对于进行系统级编程和软件开发至关重要。选择静态库或动态库取决于需求,如资源限制、程序部署的便捷性以及库更新的需求等。
Linux 下的库有两种:静态库和共享库(动态库)。静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。 3....
库主要分为静态库和动态库两种类型。 静态库(Static Library)的扩展名通常是`.a`,它的特点是将库中的所有代码直接合并到编译生成的可执行文件中。这样一来,编译出的程序自包含,不依赖外部库,便于分发和运行。...
库可以分为两种主要类型:静态库和动态库。 1. **库是什么?** 库是预编译的目标代码集合,它们以特定格式打包,供其他程序在编译或运行时调用。库包含头文件(定义函数和数据类型的接口)和库文件(实际的函数...
【Linux下动态库研究及应用】 ...总的来说,理解和掌握Linux下的动态库是系统开发的关键技能之一,它涉及到编译链接、程序运行时动态加载和环境配置等多个层面,对于提升软件的灵活性和可维护性具有重要意义。
默认情况下,Linux系统会在`/lib`和`/usr/lib`等目录下查找动态库文件。此外,用户还可以通过以下几种方式指定动态库的查找路径: - **通过`/etc/ld.so.conf`配置文件**: 用户可以在该文件中指定额外的目录,这些...
本文主要讨论两种类型的库:静态库和共享库(也称为动态库)。 首先,库是一种可执行代码的二进制形式,可以在操作系统加载到内存中执行。尽管Windows和Linux都使用库,但由于它们的体系结构差异,它们的库文件是不...
库还可以以共享库(Shared Library)和动态库(Dynamic Library)的形式存在,两者在Linux和其他类UNIX系统中通常是同义词,都指的是在程序运行时加载的库。与Windows下的.dll文件类似,这些库在编译时仅作为引用,...
在本文中,我们将深入探讨OpenCV 2.4.13版本的静态库,特别关注其在Linux环境下的应用。 首先,OpenCV 2.4.13是一个较旧但仍然广泛使用的版本,它提供了丰富的功能,如图像处理、特征检测、对象识别、机器学习等。...
在Linux下,使用静态库需要在编译时指定库的搜索路径(-L)和库名(-l),例如: ```bash g++ TestStaticLibrary.cpp -L../StaticLibrary -lstaticmath ``` 【动态库】 动态库(如Linux下的`.so`,Windows下的`....
通过这个实验,我们可以更好地理解静态库和动态库在Linux环境下的创建、使用和管理方式,以及它们在软件开发中的作用和优势。库的存在极大地提高了代码的复用性和效率,减少了重复工作,是现代软件开发不可或缺的一...
在软件开发中,动态库和静态库是两种常见的库文件类型。动态库(.dll 文件)在运行时被加载到应用程序中,而静态库(.lib 文件)则在编译时与应用程序链接在一起。本篇文章将详细介绍如何在VS2015中编译动态库并进行...
在Windows的VS中,使用静态库的方法包括在项目的“属性面板”中添加引用,或者在编译链接时指定库的路径和名称。 总的来说,静态库提供了一种便捷的方式来封装和重用代码,但同时也可能导致可执行文件变大和资源...
在Linux系统编程中,理解和掌握静态库和动态库的制作以及GDB调试是至关重要的技能。本资料包包含了关于这些主题的详细教程,通过C语言实现来帮助学习者深入理解。 首先,我们来讨论静态库。静态库是将多个目标文件...