天天看点

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

目录

一、Linux系统中函数库的类型

二、hello实例使用库

(一)、准备步骤

(二)、静态库使用

(三)、动态库使用

(四)、静态库与动态库比较

三、静态库实例

(一)、构建新文件夹,编写程序

(二)、静态库.a 文件的生成与使用

(三)、共享库.so 文件的生成与使用

四、动态库实例

(一)、程序编写 

(二)、用gcc分别编译为3个.o 目标文件 

(三)、将目标文件生成静态.a文件

(四)、观察文件大小

(五)、将目标文件生成动态库.so文件并与main函数链接

(六)、记录大小并与静态库对比

五、实验总结

六、参考文献

一、Linux系统中函数库的类型

函数库分为静态库和动态库。

  • 静态库

    在程序编译时会被连接到目标代码中,程序运行是则不需要静态库的存在。

  • 动态库

    在程序编译时不会被连接到目标代码中,而是程序运行时载入的。

    两者区别:前者是编译连接的,后者是程序运行载入的。

二、hello实例使用库

(一)、准备步骤

1.创建一个作业目录test1,保存本次练习文件。

mkdir test1
cd test1
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

2.hello代码 ,使用gedit文本编辑器生成hello.c,hello.h,main.c三个文件,三个文件源代码如下

程序一:hello.h文件

#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
           

 程序二:hello.c 

#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
           

程序三:main.c

#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
           

3.将 hello.c 编译成.o 文件并观察是否编译成功 

gcc -c hello.c
 ls
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 4.由.o 文件创建静态库并观察

创建静态库的工具:ar

静态库文件命名规范:以lib作为前缀,是.a文件

ar -crv libmyhello.a hello.o
 ls
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(二)、静态库使用

 1.含这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明静态库名,gcc 将会从 静态库中将公用函数连接到目标文件中。注意,gcc 会在静态库名前加上前缀 lib,然后追 加扩展名.a 得到的静态库文件名来查找静态库文件。

方法一:

gcc -o hello main.c -L. –lmyhello
           

方法二:

gcc main.c libmyhello.a -o hello
           

 方法三:

先生成 main.o,再生成可执行文件

gcc -c main.c
gcc -o hello main.o libmyhello.a
           

本次采用的是方法三,操作结果为:  

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 2.验证静态库是否生成成功

打开文件

./hello
           

删除静态库文件试试公用函数 hello 是否真的连接到

rm libmyhello.a
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 3.通过观察发现程序照常运行,证明表明静态库跟程序执行没有联系以及静态库中的公用函数是在编译过程中直接被调用的。 

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 (三)、动态库使用

1.创建动态库

创建动态库的工具:gcc

动态库文件命名规范:以lib作为前缀,是.so文件

gcc -shared -fPIC -o libmyhello.so hello.o

shared:表示指定生成动态链接库,不可省略

-fPIC:表示编译为位置独立的代码,不可省略

gcc -shared -fPIC -o libmyhello.so hello.o
ls
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 2.在程序中使用动态库 

输入命令gcc main.c libmyhello.so -o hello 或 gcc -o hello main.c -L. -lmyhello

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

发现在显示文件时没有问题,但在./hello 会提示出错,因为虽然连接时用的是当前目录的动态库,但是运行时,是到 /usr/lib 中找库文件的,将文件 libmyhello.so 复制到目录/usr/lib 中就可以了。 

mv libmyhello.so /usr/lib
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 发现无权限,此时我们可以用sudo命令解决

sudo mv libmyhello.so /usr/lib
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(四)、静态库与动态库比较

1.先删除除.c 和.h 外的所有文件,恢复成我们刚刚编辑完举例程序状态

sudo rm -f hello hello.o /usr/lib/libmyhello.so
ls
           

2.再来创建静态库文件 libmyhello.a 和动态库文件 libmyhello.so 

gcc -c hello.c
ar -cr libmyhello.a hello.o
gcc -shared -fPIC -o libmyhello.so hello.o
ls
           

3.运行 gcc 命令来使用函数库 myhello 生成目 标文件 hello,并运行程序 hello

gcc -o hello main.c -L. -lmyhello
           

 4.结果观察

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 发现在执行可执行文件,会报一个错误,可见当静态库和动态库同时存在的时候,程序会优先使用动态库。

三、静态库实例

(一)、构建新文件夹,编写程序

A1.c

#include <stdio.h>
void print1(int arg){
printf("A1 print arg:%d\n",arg);
}
           

A2.c

#include <stdio.h>
void print2(char *arg){
printf("A2 printf arg:%s\n", arg);
}
           

A.h

#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif
           

test.c

#include <stdlib.h>
#include "A.h"
int main(){
print1(1);
print2("test");
exit(0);
}
           

 程序构建如下: 

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(二)、静态库.a 文件的生成与使用

1.生成目标文件

gcc -c A1.c A2.c
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 2.生成静态库.a 文件

ar crv libafile.a A1.o A2.o
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 3.使用.a 库文件,创建可执行程序(若采用此种方式,需保证生成的.a 文件与.c 文件保 存在同一目录下,即都在当前目录下)

gcc -o test test.c libafile.a
./test
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(三)、共享库.so 文件的生成与使用

1.生成目标文件(xxx.o)(此处生成.o 文件必须添加"-fpic"(小模式,代码少),否则在生成.so 文件时会出错)

gcc -c -fpic A1.c A2.c
           

 2.生成共享库.so 文件

gcc -shared *.o -o libsofile.so
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 3.使用.so 库文件,创建可执行程序

gcc -o test test.c libsofile.so
./test
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献
 解决办法:这是由于 linux 自身系统设定的相应的设置的原因,即其只在/lib and /usr/lib 下搜索对应 的.so 文件,故需将对应 so 文件拷贝到对应路径。 
sudo cp libsofile.so /usr/lib
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献
 同时可直接使用 gcc -o test test.c -L. -lname,来使用相应库文件 其中, -L.:表示在当前目录下,可自行定义路径 path,即使用-Lpath 即可。 -lname:name:即对应库文件的名字(除开 lib),即若使用 libafile.a,则 name 为 afile; 若要使用 libsofile.so,则 name 为 sofile)。

四、动态库实例

详细过程可参照hello程序过程

(一)、程序编写 

 程序一:lcx.c

float x2x(int a,int b)
{
	float c=0;
	c=a+b;
	return c;
}
           

程序二:lcy.c

float x2y(int a,int b)
{
	float c=0;
	c=a*b;
	return c;
}
           

 程序三:lc.h

#ifndef LC_H
#define LC_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif
           

程序四:main.c

#include<stdio.h>
#include"lc.h"
void main()
{
	int a,b;
	printf("Please input the value of a:");
	scanf("%d",&a);
	printf("Please input the value of b:");
	scanf("%d",&b);
	printf("a+b=%.2f\n",x2x(a,b));
	printf("a*b=%.2f\n",x2y(a,b));
}
           

 代码运行如下:

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(二)、用gcc分别编译为3个.o 目标文件 

gcc -c lcx.c lcy.c main.c
           
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(三)、将目标文件生成静态.a文件

ar crv liblc.a lcx.o lcy.o
gcc -o main main.o liblc.a
           
注:在进行文件链接时,务必要注意需要用之前生成的.o文件,不然的话会报错 

代码运行如下:

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(四)、观察文件大小

在linux下使用“ls -l”或者“ls -al”或者“ll”命令查看文件及目录详情
在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(五)、将目标文件生成动态库.so文件并与main函数链接

gcc -shared -fPIC -o liblc.so lcx.o lcy.o
gcc -o main main.o liblc.so
           

 代码运行如下:

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

(六)、记录大小并与静态库对比

动态库:

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 静态库:

在Linux系统(Ubuntu)下静态库与动态库文件的生成与使用一、Linux系统中函数库的类型二、hello实例使用库三、静态库实例四、动态库实例五、实验总结六、参考文献

 对比可知,静态库占用空间更少。

五、实验总结

       通过本次实验,使我初次了解并熟悉了静态库和动态库的相关知识,使我能够自主的生成静态库和动态库,进一步理解二者之间的差别。同时通过本次实验,加强了我对 Linux系统的运行操作,加强了对gcc等相关编译工具的运用。

六、参考文献

gcc生成静态库.a和动态库.so_Harriet的博客-CSDN博客

Ubuntu实操二:静态库与动态库文件的生成与使用_Lc-Yusheng的博客-CSDN博客