库文件:静态库与动态库的生成和使用

0.引言

当进行C语言的编写时,想要查看标准库的某个函数是怎样实现的,比如 stdio.h 里的 printf 函数,跳转后只能看见函数声明,而无法跳转到函数的定义处,为什么无法查看函数的定义,这就涉及到库文件使用。

1.库文件是什么

C程序由 .c 文件最终变成可执行文件要经历预编译,编译,汇编和链接过程,在 Linux 下不同的过程分别生成如下文件 .i,.s,.o 和最终的可执行文件。而库文件就是一组预先编译好的函数的集合,它由 .o 文件生成,而 .o 是一个二进制文件,里面的内容是无法直接理解的,这也是为什么查看不了库中函数的定义,不能看,只能用。Linux 中库的位置一般在 /lib,/usr/lib 和 /usr/lib64 下,而库的头文件一般放在 /usr/include 下。库有两种,一种是静态库,命名形式是 libxx.a,一种是动态库(又叫共享库),命名形式是 libxx.so

2.静态库的生成与使用

2.1.静态库的生成

创建两个 .c 文件和一个 .h 文件,其中 add.c 和 mul.c 文件中包含函数的定义,foo.h 文件中包含函数的声明,具体内容如下。
在这里插入图片描述

首先将需要生成库文件的所有 .c 文件编译生成 .o 文件。
在这里插入图片描述

利用 ar 命令将所有 .o 文件生成静态库,需要三个参数:c 创建库,r 将方法添加到库中,v 显示过程。
在这里插入图片描述

其中,libfoo.a 就是所生成的静态库。

2.2.静态库的使用

编写一个 main.c 文件,其中调用 add 和 mul 两个函数。
在这里插入图片描述

直接利用 libfoo.a 和 main.c 文件生成可执行文件,涉及到两个参数:-L 指定所使用的静态库的位置,-l 指定静态库的名字(去掉静态库名字里的前缀 lib 和后缀 .a)。
在这里插入图片描述

3.动态库的生成与使用

3.1.动态库的生成

同样利用 add.c 和 mul.c 来生成动态库,其中 foo.h 中是函数的声明,add.c 和 mul.c 中是函数的定义。
在这里插入图片描述

首先将需要生成库文件的所有 .c 文件编译成 .o 文件。
在这里插入图片描述

使用 gcc 命令和所有 .o 文件来生成动态库。
在这里插入图片描述

其中,libfoo.so 就是所生成的动态库。

3.2.动态库的使用

编写一个 main.c 文件,其中调用 add 和 mul 两个函数。
在这里插入图片描述

直接利用 libfoo.so 和 main.c 文件生成可执行文件,涉及到两个参数:-L 指定所使用的动态库的位置,-l 指定动态库的名字(去掉动态库名字里的前缀 lib 和后缀 .so)。需要注意的一点是,如果库的存储路径下存在同名的静态库和动态库,gcc 默认使用动态库。
在这里插入图片描述

gcc 命令执行完之后会生成可执行程序 main,执行 main 会出现报错。
在这里插入图片描述

原因是程序运行时加载动态库,找不到对应的动态库文件 libfoo.so,这是由于虽然用参数 -L 指定了路径,但系统仍然会按照默认方式去存储库的标准位置(/lib 或者 /usr/lib)加载动态库,而不会在当前位置中查找,解决该问题有两种方式:1.将生成的动态库拷贝到 /usr/lib 下,再执行 gcc 命令;2.修改环境变量 LD_LIBRARY_PATH 来指定加载动态库的路径。
方式一:
在这里插入图片描述

后面两条命令将动态库 libfoo.so 移出来,并检查 /usr/lib 路径下不存在 libfoo.h。

方式二:
修改环境变量 LD_LIBRARY_PATH。
在这里插入图片描述

其中主要涉及到的命令有

export LD_LIBRARY_PATH=.    //添加环境变量(赋值运算符两边不要有空格)
echo $LD_LIBRARY_PATH       //查看环境变量的值
unset LD_LIBRARY_PATH       //删除环境变量

4.静态库与动态库的区别

首先利用相同的程序 add.c mul.c 生成 .o 文件,分别按之前的步骤生成静态库 libfoo1.a 和动态库 libfoo2.so,并将动态库 libfoo2.so 移动到 /usr/lib 下。然后,使用相同的 main.c 文件,利用 gcc 命令生成可执行文件 main1 (使用静态库 libfoo1.a 生成) main2 (使用动态库 libfoo2.so 生成),最后查看两个可执行文件的大小可以发现由静态库生成的可执行文件要比由动态库生成的可执行文件大。
在这里插入图片描述

原因是,静态库在链接时将用到的方法包含到最终的可执行文件中,而动态库不包含,只做标记,在程序运行时才动态加载,所以生成的可执行文件更小。由于上面这个原因,每个使用静态库的应用程序都需要拷贝静态库到可执行文件中,所以用静态库生成的可执行程序比较大,一旦链接完成,在执行程序的时候就不需要原来的静态库;而动态库在链接的时候并没有被拷贝到可执行文件中,只是做了标记,程序运行时才动态加载,因此可执行程序比较小,然而,程序运行时需要运行环境提供相应的动态库。
动态库相比于静态库的优点,使用动态库更有利于程序的更新与升级,不必重新编译整个可执行文件,只需要用新版本的动态库替换掉旧版本的动态库即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值