Linux系统下可执行程序的编译、组装过程

一. 用gcc生成静态库和动态库源程序准备

1.1 概念

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

1.2 编辑生成例子程序

在终端执行以下命令,创建一个目录文件

mkdir test1
cd test1

在这里插入图片描述
使用vim编辑器,编写3个c语言文件

注:若没有安装 vim编辑器,可以输入命令:sudo apt install vim 进行安装。

运行命令vi hello.h
代码如下:

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

注意:进入vim,开始编辑需要点击键盘“i”,编辑完成后,按键盘“Esc”,再输入“:wq”,表示退出并保存。

运行命令vi hello.c
代码如下:

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

运行命令vi main.c
代码如下:

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

1.3 将 hello.c 编译成.o 文件

输入命令使得.c文件变为.o文件,无论静态库,还是动态库,都是由.o 文件创建的。具体命令如下:

gcc -c hello.c

运行 ls 命令看是否生存了 hello.o 文件

ls

得到如下结果:
在这里插入图片描述

二. 静态库创建及使用

2.1创建静态库

静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a,创建静态库用 ar 命令,具体命令如下:

ar -crv libmyhello.a hello.o

运行 ls 命令看看是否生存了libmyhello.a 文件

ls

2.2 使用静态库

静态库制作完了,使用它内部的函数,只需要在使用到这些公用函数的源程序中 含这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明静态库名,gcc 将会从静态库中将公用函数连接到目标文件中。
(注意:gcc 会在静态库名前加上前缀 lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。)
在程序 3:main.c 中,我们包含了静态库的头文件 hello.h,然后在主程序 main中直接调用公用函数 hello。下面先生成目标程序 hello,运行 hello 程序。

方法一:
命令如下:

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

运行程序,输入以下命令:

./hello

结果如下:
在这里插入图片描述
方法二:
命令如下:

gcc main.c libmyhello.a -o hello

运行./hello,结果如下:
在这里插入图片描述
方法三

先生成main.o,命令如下:

gcc -c main.c

在生成可执行文件,命令如下:

gcc -o hello main.o libmyhello.a

运行./hello,结果如下:
在这里插入图片描述

说明:即使删掉 libmyhello.a 静态库文件,hello可执行文件照常运行,说明静态库中的公用函数已经链接到 .o 目标文件中了。

运行命令rm libmyhello.a删除libmyhello.a静态库文件,同样运行命令./hello查看结果

三. 动态库创建及使用

3.1 动态库创建

动态库文件命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件拓展名为.so。

命令如下:

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

同样我们使用ls命令查看
在这里插入图片描述

3.2 使用动态库

在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的声明原型,然后用gcc命令生成目标文件时指明动态库名进行编译。

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

或者

gcc main.c libmyhello.so -o hello

运行./hello发现有错误
在这里插入图片描述
程序报错为找不到动态库文件libmyhello.so。程序运行时,会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上诉错误而终止程序运行。我们将文件libmyhello.so复制到目录/usr/lib中就可以了。

复制命令:mv libmyhello.so /usr/lib

当我们将上述命令输入之后,发现并不能直接复制,那我们就需要切换到root用户模式再执行操作。
在这里插入图片描述

注意:若第一次使用 root 用户,要先激活,使用命令:sudo passwd root
然后连续输入两个密码即可

在这里插入图片描述
然后再输入su,接着输入密码就进入root用户模式了,再在此模式下复制动态库文件,最后输入exit退出该模式就结束了。
在这里插入图片描述
然后我们再次执行./hello,运行成功
在这里插入图片描述

当静态库和动态库同名时,gcc优先使用动态库

四、库具体使用实例

4.1 源码

创建一个文件夹Test2

mkdir Test2
cd Test2

代码如下

x2x.c
在这里插入图片描述
x2y.c
在这里插入图片描述

test.h
在这里插入图片描述
main.c
在这里插入图片描述
结果如下:
在这里插入图片描述

4.2 静态库使用

将.c文件编译成.o文件
在这里插入图片描述
生成静态库.a文件
在这里插入图片描述
链接静态库文件并执行
在这里插入图片描述
结果正确!!

接下来使用size test命令查看test文件大小

在这里插入图片描述
使用ll命令可以查看文件夹所有文件的大小
在这里插入图片描述

4.3 动态库使用

删除静态库文件和可执行文件,只保留目标文件(方便比较大小)
在这里插入图片描述

生成.so文件
在这里插入图片描述

-fpic(小模式,代码少)必须添加

使用.so库文件,创建可执行程序
在这里插入图片描述

发现有错误,这是由于linux自身系统设定的相应设置的原因,即其只在/lib and/usr/lib下搜索对应的.so文件,故需将对应so文件拷贝到对应的路径(在文章开始创建动态库时也讲到过)

修改后,结果正确!!
在这里插入图片描述
查看文件大小
在这里插入图片描述
在这里插入图片描述

4.4 总结

通过比较我们发现静态库和动态库生成的test可执行文件是差不多大的。

五、总结

通过这次实验,了解到了Linux系统下静态库文件和动态库文件如何生成,以及静态库.a.与.so文件该如何使用

六、参考文献

用gcc生成静态库和动态库


版权声明:本文为qq_55691662原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。