库,本质上来说是一种可执行代码的二进制形式(一个文件包含了一些编译好的代码和数据),可以被操作系统载入内存执行。
程序函数库可以使整个程序更加模块化,更容易重新编译,而且更方便升级。
程序函数库可分为2种类型:
静态函数库,动态加载函数库
linux下:
静态库:lib库名.a
动态库:lib库名.so(shared object)
window下:
静态库:lib库名.lib
动态库:lib库名.dll(dynamic link library)
简介:
之所以称之为静态库,是因为在链接阶段,会将汇编生成的目标文件.o 与 引用的库一起链接到可执行文件中。对应的链接方式称为 静态链接。
如果多个进程需要引用到静态库,在内存中就会存在多份拷贝。
静态库的特点:
①静态库对函数库的链接是在编译期完成的。执行期间代码装载速度快。
②使可执行文件变大,浪费空间和资源(占空间)。
③对程序的更新、部署与发布不方便,需要全量更新。如果 某一个静态库更新了,所有使用它的应用程序都需要重新编译、发布给用户。
优点:
1)静态库在编译的时候就被打包到应用程序中,所以其加载的速度快
2)发布程序的时候无需提供静态库,因为已经在app中,移植方便
缺点:
1)链接时完整的拷贝到可执行文件中,被多次使用就会有多份冗余拷贝
简介:
在程序编译时并不会链接到目标代码中,而是在运行时才被载入。不同的应用程序如果调用相同的库,那么在内存中只需要有一份该共享库的实例,避免了空间浪费问题。同时也解决了静态库对程序的更新的依赖,用户只需更新动态库即可。
动态库特点:
①动态库把对一些库函数的链接载入推迟到程序运行时期(占时间)。
②可以实现进程之间的资源共享。(因此动态库也称为共享库)
③将一些程序升级变得简单,不需要重新编译,属于增量更新。
优点:
1)链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序可以共用,节省内存
2)程序升级简单,因为app中没有库的源代码,升级之后只要库的名字不变,函数名与及参数不变,只是做了优化,就能加载成功
缺点:
1)加载速度比静态库慢
2)发布程序时需要提供依赖的动态库
静态库文件名的命名方式是libxxx.a
,库名前加lib
,后缀用.a
,xxx
为静态库名。
① 准备需要做成库的文件.c或.cpp文件
② 首先将.c文件生成.o文件,通过 gcc xxxx.c -c
生成
③ 将.o文件进行打包成后缀为.a的静态库文件,执行下列命令进行打包:
ar rcs libxxx.a xxx.o
gcc main_cal.c -lstaticCal -L ./ -o mainTest
-l:指定要用的静态库,库名要看头去尾(即要去掉lib和后缀.a),(-lmystatic)
-L:告诉gcc编译器从-L指定的路径去找静态库,如果没有指定,则默认从/usr/lib或/usr/local/lib去找 ,则这里有指定./,-L ./的意思就是从当前路径去找
-o(小写的O):指定生成的可执行文件
例:要生成库的文件是calculator.c
示例代码:
int add(int a,int b)
{return a+b;
}
int sub(int a,int b)
{return a-b;
}float div(int a,int b)
{return (float)a/b;
}
int mul(int a,int b)
{return a*b;
}
int add(int a,int b);
int sub(int a,int b);
float div(int a,int b);
int mul(int a,int b);
#include
#include "calculator.h"int main()
{int a,b;char operator;printf("输入数字n1:\n");scanf("%d",&a);printf("输入数字n2:\n");scanf("%d",&b);getchar();//输入第二个数字后回敲入一个空格,需要被接受掉,否则后面的运算符无法接受printf("输入算法(+,-,*,/):\n");scanf("%c",&operator);printf("输入的算式是:%d %c %d",a,operator,b);switch (operator){case'+' :printf(" = %d\n",add(a,b));break;case'-':printf(" = %d\n",sub(a,b));break;case'*':printf(" = %d\n",mul(a,b));break;case'/':printf(" = %f\n",div(a,b));break;}return 0;
}
① 首先生成.o文件
gcc calculator.c -c
② 将.o文件制作为静态库:
ar rcs libstaticCal.a calculator.o
生成了libstaticCal.a库文件
③ 使用静态库
gcc main_cal.c -lstaticCal -L ./ -o mainTest
动态库的命名方式与静态库类似,前缀相同,为lib
,后缀变为.so
,所以为libxxx.so
后缀用.so
,xxx
为动态库名。
① 准备需要做成库的文件.c或.cpp文件
② 首先将.c文件生成.o文件,需要加-fpic:gcc xxx.c -c -fpic
-fpic:标准,fPIC 选项作用于编译阶段,在生成目标文件时就得使用该选项,以**生成位置无关的代码**。
③ 将.o文件进行打包成后缀为.so的动态库文件,执行下列命令进行打包:
gcc -shared xxx.o -o libxxx.so
-shared:指定生成动态库
gcc main_cal.c -ldynamicCal -L ./ -o mainTest
与静态库的使用方法一致,但是当运行mainTest时会报错:
此时会提示No such file or directory,这是因为在调用动态库时,在运行过程中会寻找此库一般会在 /usr/lib/
目录下找文件;从而找不到libdynamicCal.so
这个文件。
因此这里需要设置动态可以的搜索路径
/usr/lib/
中:sudo cp libdynamicCal.so /usr/lib
可以正常使用动态库
export LD_LIBRARY_PATH="/home/zh1/STEP3/库的认知"
可正常运行
但是这种方法有缺陷,重启后变无法找到刚配置的环境变量,需要重新配置,若采用这种方法使用动态库一般需要编写脚本,例:
export LD_LIBRARY_PATH="/home/zh2/STEP3/库的认知"./mainTest
赋予脚本可执行权限
chmod +x start.sh
执行脚本即可:
在 /etc/ld.so.conf.d
路径中 添加 *.conf
例:mylib.conf
cd /etc/ld.so.conf.d
创建mylib.conf
文件
sudo vi mylib.conf
将所要指定的动态库搜索路径加入mylib.conf
中
再执行:
sudo ldconfig
打开/etc/profile
sudo vi /etc/profile
在最后添加下列内容:
export LD_LIBRARY_PATH=/home/zh1/STEP3/库的认知:$LD_LIBRARY_PATH
保存退出后执行:
source /etc/profile
下一篇:从内核角度看TCP三次握手