一、Linux如何制作静态库
静态库的本质就是将多个目标文件打包成一个文件
链接静态库的过程就是将库中被调用的代码复制到调用模块中
静态库的扩展名:.a 例如:libXXXX.a
以数学库为例,
cpp
/******compute.h*****/
#ifndef _COMPUTE_H
#define _COMPUTE_H
extern int add(int,int);
extern int sub(int,int);
#endif
/******compute.c*****/
#include "compute.h"
int add(int a,int b){
return a + b;
}
int sub(int a,int b){
return a - b;
}
/******show.h*****/
#ifndef _SHOW_H
#define _SHOW_H
extern void show(int a,char b,int c ,int d);
#endif
/******show.c*****/
#include "show.h"
#include <stdio.h>
void show(int a,char b,int c,int d){
printf("%d %c %d %d\n",a,b,c,d);
}
/******main.c*****/
#include "compute.h"
#include "show.h"
#include <stdio.h>
int main(void){
int a = 123;
int b = 456;
show(a,'+',b,add(a,b);
return 0;
}
制作静态库的步骤
第一步,完成功能需求代码的编写(以数学库为例)
第二步,编译成目标文件,需要编译成.o文件
第三步,将多个目标文件制作成静态库
ar [选项] <静态库文件> [目标文件列表]
-r 将目标插入到静态库中,已存在则更新
-q 将目标文件追加到静态库尾
-d 从静态库中删除目标文件
-t 列表显示静态库中的目标文件
-x 将静态库展开为目标文件
ar -r libmath.a compute.o show.o //将多个目标文件制作成静态库
制作完成后就是使用静态库。使用静态库的步骤:
第一步,完成使用静态库的代码编写(main.c)
第二步,编译并链接静态库
-直接链接静态库
gcc main.c libmath.a //同一路径下
-用-l指定库名 -L指定库路径
gcc main.c -lmath -L<路径>
也可以使用LIBRARY_PATH环境变量指定库路径
export LIBRARY_PATH=$LIBRARY_PATH:<添加的路径>
二、Linux如何制作动态库
动态库和静态库不同,链接动态库不需要将被调用的函数代码复制到包含调用代码的可执行文件中,相反链接器会在调用语句处嵌入一段指令,在该程序执行到这段指令时,会加载该动态库并寻找被调用函数的入口地址并执行。
如果动态库中的代码同时为多个进程所用,动态库在内存的实例只有一份,为所有使用该库的进程所共享,因此动态库亦称共享库。
例如:libXXXX.so
制作动态库的步骤:
第一步,完成功能需求的代码编写
第二步,编译生成动态库所需的目标文件(.o文件)
gcc -c -fpic .c文件
pic:位置无关码,了解
第三步,将多个目标文件制作成动态库
gcc -shared 多个目标文件 -o libmath.so
制作完成后就是使用动态库。使用动态库的步骤:
第一步,完成使用动态库的代码编写(main.c)
第二步,编译并链接动态库
-直接链接静态库
gcc main.c libmath.so //同一路径下
-用-l指定库名 -L指定库路径
gcc main.c -lmath -L<路径>
也可以使用LIBRARY_PATH环境变量指定库路径
export LIBRARY_PATH=$LIBRARY_PATH:<添加的路径>
此时在运行可执行文件时发现,出现下列问题,解决方法就是链接器没有在运行时链接动态库
运行阶段需要保证LD_LIBRARY_PATH环境变量中包含共享库所在路径用以告知链接器在运行时链接动态库。
export LD_LIBRARY_PATH=&LD_LIBRARY_PATH:<路径>
在可执行程序的链接阶段,并不将所调用函数的二进制代码复制到可执行程序中,而只是将该函数在共享库中的地址嵌入到调用模块中,因此运行时需要依赖共享库。
三、动态库的动态加载
动态加载:在程序执行的过程中,开发人员可以动态加载共享库(什么时候用什么时候加载),这样可以提高内存利用率。
在程序中动态加载共享库需要调用一组特殊的函数,他们被声明于一个专门的头文件中,并在一个独立的库中予以实现。
使用这组函数需要包含此文件,并链接该库
#include <dlfcn.h>
-ldl
函数:dlopen,dlsym,dlclose,dlerror
cpp
#include <stdio.h>
#include "compute.h"
#include "show.h"
#include <dlfcn.h>
int main(void){
//1.将共享库载入内存
void* handle = dlopen("./libmath.so",RTLD_LAZY);
if(handle == NULL){
fprintf(stderr,"error:%s\n",dlerror());
return -1;
}
//2.从共享库中获取函数地址(函数指针)
int (*add)(int,int) = dlsym(handle,"add");
if(add == NULL){
fprintf(stderr,"error:%s\n",dlerror());
return -1;
}
int (*sub)(int,int) = dlsym(handle,"sub");
if(sub == NULL){
fprintf(stderr,"error:%s\n",dlerror());
return -1;
}
void (*show)(int,char,int,int) = dlsym(handle,"show");
if(show == NULL){
fprintf(stderr,"error:%s\n",dlerror());
return -1;
}
//3.使用
int a = 123;
int b = 456;
show(a,'+',b,add(a , b));
//4.卸载动态库
if(dlclose(handle)){
fprintf(stderr,"error:%s\n",dlerror());
return -1;
}
}
四、rootfs根文件系统在Linux下制作动态库
第一步,完成功能需求文件编写。
第二步,编译成目标文件,
交叉编译器 -c -fpic
第三步, 将多个目标文件制作成动态库
交叉编译器 -shared 目标文件 -o libxxx.so
第四步,使用文件编写,
交叉编译器 使用文件 -l动态库名 -L路径 -o 可执行文件
最后便是路径选择,参照制作动态库