Linux库概念及相关编程
转载:https://blog.csdn.net/weixin_45525272/article/details/121051636?ops_request_misc=&request_id=&biz_id=102&utm_term=Linux%E5%85%B1%E4%BA%AB%E5%BA%93%E9%9D%99%E6%80%81%E5%BA%93%E5%8A%A8%E6%80%81%E5%BA%93&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-121051636.142%5Ev85%5Einsert_down28,239%5Ev2%5Einsert_chatgpt&spm=1018.2226.3001.4187
作者:杨 戬
一、分文件编程的好处
- 功能分模块
- 主程序简洁
- 方便调试
二、Linux库
- 库的介绍
库是二进制文件, 是源代码文件的另一种表现形式, 是加了密的源代码;
是一些功能相近或者是相似的函数的集合体。 - 使用库有什么好处
2.1 提高代码的可重用性, 而且还可以提高程序的健壮性;
2.2 可以减少开发者的代码开发量, 缩短开发周期。 - 库制作完成后, 如何给用户使用
3.1 头文件—包含了库函数的声明
3.2 库文件—包含了库函数的代码实现
注意: 库不能单独使用, 只能作为其他执行程序的一部分完成某些功能, 也就是说只能被其他程序调用才能使用。
三、静态库
- 静态库可以认为是一些目标代码的集合, 是在可执行程序运行前就已经加入到执行码中, 成为执行程序的一部分. 按照习惯, 一般以.a做为文件后缀名。
- 优点:
2.1 静态库被打包到应用程序中加载速度快
2.2 发布程序无需提供静态库,因为已经在app中,移植方便 - 缺点:
3.1 链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
3.2 更新、部署、发布麻烦。 - 制作:
4.1 将c源文件生成对应的.o文件
gcc -c func1.c func2.c
或者分别生成.o文件:
gcc -c func1.c -o func1.o
gcc -c func2.c -o func2.o
4.2 使用打包工具ar将准备好的.o文件打包为.a文件
在使用ar工具是时候需要添加参数rcs
r更新、c创建、s建立索引
命令:ar rcs 静态库名 .o文件
ar rcs libtest1.a func1.o func2.o - 静态库的使用
5.1 静态库制作完成之后, 需要将.a文件和头文件一定发布给用户。
5.2 假设测试文件为main.c, 静态库文件为libtest1.a, 头文件为head.h。
gcc -o main1 main.c -L./ -ltest1 -I./
L:指定要连接的库的所在目录
l:指定链接时需要的静态库, 去掉前缀和后缀
I: 指定main.c文件用到的头文件head.h所在的路径
四、动态库
- 共享库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的拷贝,规避了空间浪费问题。
- 动态库在程序运行时才被载入, 也解决了静态库对程序的更新、部署和发布会带来麻烦。 用户只需要更新动态库即可,增量更新。
- 按照习惯, 一般以”.so”做为文件后缀名. 共享库的命名一般分为三个部分:
前缀:lib
库名称:自己定义即可, 如test
后缀:.so
所以最终的静态库的名字应该为:libtest.so - 优点:
4.1 链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序可以共用,节省内存。
4.2 程序升级简单,因为app里面没有库的源代码,升级之后只要库的名字不变,函数名以及参数不变,只是实现做了优化,就能加载成功。 - 缺点:
5.1 加载速度比静态库慢
5.2 发布程序需要提供依赖的动态库 - 动态库的制作
gcc -shared -fpic func1.c -o libtest.so
shared:指定生成动态库 - 动态库的使用
gcc main.c -I./ -L./ -ltest2 -o main2
使用动态库时需要先安装动态库。
临时设置LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yang/C/sharelib/libtest2.so
五、静态库源程序
- func1.c:库的C源文件
#include <stdio.h>
int ret_sum(int x, int y)
{
return (x+y);
}
int ret_dec(int x, int y)
{
return (x-y);
}
int ret_multi(int x, int y)
{
return (x*y);
}
double ret_div(int x, int y)
{
return ((double)(x/y));
}
- func1.h:库的h头文件
int ret_sum(int x, int y);
int ret_dec(int x, int y);
int ret_multi(int x, int y);
double ret_div(int x, int y);
- func2.c:主函数文件
#include <stdio.h>
#include "func1.h"
int main()
{
int x, y;
printf("input two int\n");
scanf("%d%d",&x,&y);
printf("sum = %d\n",ret_sum(x, y));
printf("dec = %d\n",ret_dec(x, y));
printf("multi = %d\n",ret_multi(x, y));
printf("div = %lf\n",ret_div(x, y));
return 0;
}
六、动态库源程序
- func1.c:动态库C源文件
#include <stdio.h>
int ret_sum(int x, int y)
{
return (x+y);
}
int ret_dec(int x, int y)
{
return (x-y);
}
int ret_multi(int x, int y)
{
return (x*y);
}
double ret_div(int x, int y)
{
return ((double)(x/y));
}
- func1.h:动态库h头文件
int ret_sum(int x, int y);
int ret_dec(int x, int y);
int ret_multi(int x, int y);
double ret_div(int x, int y);
- func2.c:主函数文件
#include <stdio.h>
#include "func1.h"
int main()
{
int x, y;
printf("input two int\n");
scanf("%d%d",&x,&y);
printf("sum = %d\n",ret_sum(x, y));
printf("dec = %d\n",ret_dec(x, y));
printf("multi = %d\n",ret_multi(x, y));
printf("div = %lf\n",ret_div(x, y));
return 0;
}
- 编译主程序并执行的shell脚本
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/pi/Desktop/work/c_code/2_malloc_lib/libtest.so
gcc func2.c -I./ -L./ -ltest -o main
./main