加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

Linux中的静态库与动态库

发布时间:2020-12-13 22:35:48 所属栏目:Linux 来源:网络整理
导读:什么是库文件? 库文件是事先编译好的方法的合集。比如:我们提前写好一些数据公式的实现,将其打包成库文件,以后使用只需要库文件就可以,不需要重新编写。 Linux系统中: 1.静态库的扩展名为.a; 2.动态库的扩展名为.so; 源代码到可执行程序的转换时需要

什么是库文件?

库文件是事先编译好的方法的合集。比如:我们提前写好一些数据公式的实现,将其打包成库文件,以后使用只需要库文件就可以,不需要重新编写。

Linux系统中:

1.静态库的扩展名为.a;
2.动态库的扩展名为.so;

源代码到可执行程序的转换时需要经历如下图所示的过程:

1.编译是指把用高级语言编写的程序转换成相应处理器的汇编语言程序的过程。
2.汇编是从汇编语言程序生成目标系统的二进制代码(机器代码)的过程。
3.链接是指将汇编生成的多段机器代码组合成一个可执行程序。

通过编译和汇编过程,每一个源文件将生成一个目标文件。连接器的作用就是将这些目标文件组合起来,组合的过程包括了代码段、数据段等部分的合并,以及添加相应的文件头。

最后得到的可执行文件如何作用的:

ELF文件格式包括三种主要的类型:可执行文件、可重定向文件、共享库。

1.可执行文件(应用程序)

可执行文件包含了代码和数据,是可以直接运行的程序。

2.可重定向文件(*.o)

可重定向文件又称为目标文件,它包含了代码和数据(这些数据是和其他重定位文件和共享的object文件一起连接时使用的)。

.o文件参与程序的连接(创建一个程序)和程序的执行(运行一个程序),它提供了一个方便有效的方法来用并行的视角看待文件的内容,这些.o文件的活动可以反映出不同的需要。

Linux下,我们可以用gcc -c编译源文件时可将其编译成*.o格式。

3.共享文件(*.so)

也称为动态库文件,它包含了代码和数据(这些数据是在连接时候被连接器ld和运行时动态连接器使用的)。动态连接器可能称为ld.so.1,libc.so.1或者?ld-linux.so.1。我的CentOS6.0系统中该文件为:/lib/ld-2.12.so

库是一种可执行代码的二进制格式,能够被载入到内存中执行,库分静态库和动态库两种:

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

动态库:这类库的名字一般是libxxx.M.N.so,同样的xxx为库的名字,M是库的主版本号,N是库的副版本号。当然也可以不要版本号,但名字必须有。相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。

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

制作静态链接库:

1.准备两个源码文件st1.cpp和st2.cpp,用它们来制作库libmytest.a

[email?protected]:~/development_test/static_lib_test$ cat st1.cpp 
#include <iostream>
using namespace std;
void display1()
{
    cout<<"This is my first static library!!!"<<endl;
}
[email?protected]:~/development_test/static_lib_test$ cat st2.cpp 
#include <iostream>
using namespace std;
void display2()
{
    cout<<"This is my second static library"<<endl;
}

2.把两个源码文件生成目标文件

[email?protected]:~/development_test/static_lib_test$ g++ -c st1.cpp  st2.cpp 
[email?protected]:~/development_test/static_lib_test$ ll
总用量 24
drwxrwxr-x 2 xzj xzj 4096 7月  16 15:39 ./
drwxrwxr-x 7 xzj xzj 4096 7月  16 15:26 ../
-rw-rw-r-- 1 xzj xzj  115 7月  16 15:35 st1.cpp
-rw-rw-r-- 1 xzj xzj 2680 7月  16 15:39 st1.o
-rw-rw-r-- 1 xzj xzj  113 7月  16 15:35 st2.cpp
-rw-rw-r-- 1 xzj xzj 2680 7月  16 15:39 st2.o

3.使用ar -rsv libmytest.a st1.o st2.o制作静态库

[email?protected]:~/development_test/static_lib_test$ ar -rsv libmytest.a st1.o st2.o
ar: 正在创建 libmytest.a
a - st1.o
a - st2.o
[email?protected]:~/development_test/static_lib_test$ ll
总用量 32
drwxrwxr-x 2 xzj xzj 4096 7月  16 15:42 ./
drwxrwxr-x 7 xzj xzj 4096 7月  16 15:26 ../
-rw-rw-r-- 1 xzj xzj 5586 7月  16 15:42 libmytest.a
-rw-rw-r-- 1 xzj xzj  115 7月  16 15:35 st1.cpp
-rw-rw-r-- 1 xzj xzj 2680 7月  16 15:39 st1.o
-rw-rw-r-- 1 xzj xzj  113 7月  16 15:35 st2.cpp
-rw-rw-r-- 1 xzj xzj 2680 7月  16 15:39 st2.o
用file命令查看其属性,发现它确实是归档压缩文件
[email?protected]:~/development_test/static_lib_test$ file libmytest.a 
libmytest.a: current ar archive
用ar -t libmytest.a可以查看一个静态库包含了那些obj文件:
[email?protected]:~/development_test/static_lib_test$ ar -t libmytest.a 
st1.o
st2.o

4.写个测试程序来调用库libmytest.a中所提供的两个接口display1()和display2()。

[email?protected]:~/development_test/static_lib_test$ cat main.cpp 
void display1();
void display2();
int main()
{
    display1();
    display2();
    return 0;
}

[email?protected]:~/development_test/static_lib_test$ g++ -o run main.cpp  -L./  -lmytest
[email?protected]:~/development_test/static_lib_test$ ll
总用量 48
drwxrwxr-x 2 xzj xzj 4096 7月  16 15:54 ./
drwxrwxr-x 7 xzj xzj 4096 7月  16 15:26 ../
-rw-rw-r-- 1 xzj xzj 5586 7月  16 15:42 libmytest.a
-rw-rw-r-- 1 xzj xzj   95 7月  16 15:53 main.cpp
-rwxrwxr-x 1 xzj xzj 9424 7月  16 15:54 run* 
-rw-rw-r-- 1 xzj xzj  115 7月  16 15:35 st1.cpp
-rw-rw-r-- 1 xzj xzj 2680 7月  16 15:39 st1.o
-rw-rw-r-- 1 xzj xzj  113 7月  16 15:35 st2.cpp
-rw-rw-r-- 1 xzj xzj 2680 7月  16 15:39 st2.o

结果调用成功:
[email?protected]:~/development_test/static_lib_test$ ./run
This is my first static library!!!
This is my second static library

制作动态库

静态库*.a文件的存在主要是为了支持较老的a.out格式的可执行文件而存在的。目前用的最多的要数动态库了。

动态库的后缀为*.so。在Linux发行版中大多数的动态库基本都位于/usr/lib和/lib目录下。在开发和使用我们自己动态库之前,请容许我先落里罗嗦的跟大家唠叨唠叨Linux下和动态库相关的事儿吧。

有时候当我们的应用程序无法运行时,它会提示我们说它找不到什么样的库,或者哪个库的版本又不合它胃口了等等之类的话。那么应用程序它是怎么知道需要哪些库的呢?我们前面已几个学了个很棒的命令ldd,用就是用来查看一个文件到底依赖了那些so库文件。

Linux系统中动态链接库的配置文件一般在/etc/ld.so.conf文件内,它里面存放的内容是可以被Linux共享的动态联库所在的目录的名字。我的系统中,该文件的内容如下:

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读