博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
熟悉Linux 下静态库.a 与.so 库文件的生成与使用——实例
阅读量:3962 次
发布时间:2019-05-24

本文共 3280 字,大约阅读时间需要 10 分钟。

熟悉Linux 下静态库.a 与.so 库文件的生成与使用——实例

程序环境:VMware® Workstation 15 Pro-15.0.0,Ubuntu16.04 LTS,gcc -5.4.0

摘要:我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

本文主要通过举例来说明在Linux 中如何创建静态库和动态库,以及使用它们。
关键字:Linux,静态库,动态库
相关知识:gcc,ar

知识拓展

ar是Linux系统的一个备份压缩命令,用于创建、修改备存文件(archive),或从备存文件中提取成员文件。ar命令最常见的用法是将目标文件打包为静态链接库

一、 静态库的生成与调用

1. 主要函数编译

该过程主要进行生成.h、.c、以及主函数(main.c)

①在熟悉的目录下建立一个test文件夹,放入此次实例程序

mkdir test

进入该文件夹

cd test

②编译sub_1.h、sumfloat.c、subfloat.c、main1.c程序

用vim,nano或者gedit编写以下程序

sub_1.h代码如下:

#ifndef sub_1H					//声明头文件#define sub_1H					//宏定义#include
//预处理#include
//预处理float sumfloat(float,float); //声明sumfloat函数float subfloat(float,float); //声明subfloat函数#endif //结束

sumfloat.c代码如下:

#include"sub_1.h"					//预处理float sumfloat(float a,float b)		//sumfloat函数,浮点求和{
a+=b; return a;}

subfloat.c代码如下:

#include"sub_1.h"					//预处理float subfloat(float a,float b)		//subfloat函数,浮点相减{
a=a-b; return a;}

main1.c代码如下:

#include"sub_1.h"					//预处理void main(){
float x,y; float a=12,b=13; //a=12,b=13 x=sumfloat(a,b); //x=a+b y=subfloat(a,b); //y=a-b printf("%f+%f=%f\n",a,b,x); //打印浮点相加的值 printf("%f-%f=%f\n",a,b,y); //打印浮点相减的值}

在这里插入图片描述

2. 生成主要函数.o文件

gcc -c sumfloat.c subfloat.c

在这里插入图片描述

知识拓展

gcc 是 Gnu 的 c 编译器, gcc 在执行编译工作的时候,总共需要4步:
1、预处理,生成 .i 的文件[预处理器cpp]
2、将预处理后的文件转换成汇编语言, 生成文件 .s [编译器egcs]
3、有汇编变为目标代码(机器代码)生成 .o 的文件[汇编器as]
4、连接目标代码, 生成可执行程序 [链接器ld]
其中参数详解如下:
-c:只编译,不链接成为可执行文件,生成.o文件
-o:链接生成可执行文件,默认生成a.out文件,但可以对生成的可执行文件进行命名

3. 生成静态库.a

ar crv libafile.a sumfloat.o subfloat.o

在这里插入图片描述

知识拓展

ar命令可以用来创建修改库,也可以从库中提出单个模块。一般多用来生成静态库。
参数详解:
-c:创建一个库。不管库存不存在都将创建
-r:在库中插入模块(替换)
-v:程序执行时显示详细信息

4. 调用静态库并生成工程文件

gcc -o test main1.c libafile.a

在这里插入图片描述

./test

在这里插入图片描述

在这里我们可以查看下静态库的生成的可执行文件的大小

size test

在这里插入图片描述

二、 动态库的生成与调用

声明:本博客的动态库与静态库是分别在不同的目录下进行的编译,这里的可执行文件名一致并没有发生冲突,但如果是在同一个目录下,请将两个不同的可执行文件进行不同命名。

1. 主要函数编译

主要函数沿用以上静态库所编译生成的sub_1.h、sumfloat.c、subfloat.c、main1.c,但.o文件不同。

2. 生成主要函数.o文件

gcc -c -fpic sumfloat.c subfloat.c

在这里插入图片描述

知识拓展

-fpic: 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。(小模式,代码少)

3. 生成动态库.so

gcc -shared *.o -o libsofile.so

在这里插入图片描述

知识拓展

参数详解:
-shared:生成共享库
*.o:将当前文件目录下的.o文件批操作

4. 调用动态库并生成工程文件

gcc -o test main1.c libsofile.so

如果直接进行编写可执行文件,会出现报错。在这里插入图片描述

因为在动态库中,程序运行时,先是到/usr/lib 中找动态库文件的,所以我们需要将libsofile.so拷贝到/usr/lib中去,输入以下命令:

sudo cp libsofile.so /usr/lib

现在再输入命令

gcc -o test main1.c libsofile.so

这时就不会报错了,并生成test可执行文件。

这里提供一下解决报错的

方法二
gcc -o test main1.c -L -lname
其中,
-L:表示在当前目录下,可自行定义路径path,即使用-lpath 即可。
-lname:name:即对应库文件的名字(除开lib),即若使用libafile.a,则name 为afile;若要使用libsofile.so,则name 为sofile。

在这里插入图片描述

./test

在这里插入图片描述

这里也查看一下动态库链接生成的可执行文件的大小

size test

在这里插入图片描述

与静态库链接生成的可执行文件进行对比,发现可执行文件text静态库的代码明显多于动态库。

三、 二者之间的联系与区别

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

②当静态库和动态库同名时,gcc 命令将优先使用动态库,默认去链接/usr/lib 和/lib 等目录中的动态库,所以在生成动态库时可以进行路径链接不用进行拷贝操作。
③在静态库与动态库的可执行文件的大小比较中,发现动态库的可执行文件大小较于静态库的小很多。通过查找资料也证实了这一点,静态库是直接将需要的代码连接进可执行程序;动态库是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。文件大小关系应该是做成静态库可执行文件本身比较大,但不必附带动态库。做成动态库可执行文件本身比较小,但需要附带动态库。

四、 总结

在此次实例中,我理解到库在编程中是很重要的概念,在库中可以进行链接各种.c文件,在主函数中就可以直接调用库中的函数,不用在主函数中编译其他功能函数,减少了主函数的编译内容,对主函数也有了一定的拓展性。对静态库和动态库的调用,也使我熟悉了之间的命令操作,并在其中学习了静态库与动态库的联系与区别。

转载地址:http://kfrzi.baihongyu.com/

你可能感兴趣的文章
QTP之网页链接
查看>>
Fiddler实用教程
查看>>
从入门到深入Fiddler (一)
查看>>
从入门到深入Fiddler (二)
查看>>
Win7+php7+apache2.4
查看>>
QTP基本使用——associate actions
查看>>
charAt()方法和charCodeAt()方法—— 从字符串中选取一个字符.
查看>>
(1)Pascal 程序结构和基本语句
查看>>
LoadRunner之——脚本分析
查看>>
Advanced searching - fields reference
查看>>
Advanced searching - operators reference
查看>>
LoadRunner之——Java vuser
查看>>
LoadRunner之——场景创建、设置、运行
查看>>
QTP基本使用——Recovery Scenarios
查看>>
Ruby 的优缺点
查看>>
Ruby 教程(一)
查看>>
Ruby 教程(二)
查看>>
Android——简介
查看>>
Ruby 教程(三)
查看>>
Ruby 教程(四)
查看>>