Linux的编程库的静-动态链接的实现过程

本人的个人博客地址

-因本人才疏学浅,错误之处望大家指正批评

本文资料来源

首先我们要知道什么是库

库是什么?

库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都是从零开始,因此库的存在意义非同寻常

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.库有两种,一种是静态库,一种是动态库.Linux下的名称和Window下的名称不同.

库中可以理解为一堆封装好的函数.

库的编号

编号的约定:

library_name.major_num.minor_num.patch_num

如libgdbm.so.2.0.0

? 库名+库的类型:ligdbm.so

? 主版本:2

? 次版本号:0

? 补丁号:0

在说静态库和动态库之前我们先讲一下一个C语言从诞生到执行的全过程吧

Linux下的C语言要经过

预处理--编译--汇编--链接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ow6iRXU2-1587793310586)(http://besthpy.top/blog/20190519/SXmuEK7nvyEk.png?imageslim)]

静态库和动态库的作用

静态库、动态库区别来自[链接阶段]如何处理库、链接成可执行行程库.分别称为静态链接方式、动态链接方式.

四个步骤,并最终生成可执行文件,这个可执行文件默认保存为a.out

静态库(static library)

Linux下静态库的名称为 (.a )

Window下静态库的名称为(.lib)

静态库编写例程——liberr.h,liberr.c,errtest.c

? liberr.h:静态库头文件

? liberr.c:出错处理库实现

? errtest.c:用来测试库的程序

编写静态库

请看下文的ar命令

共享库(动态链接库)

Linux下动态库的名称为 (.so )

Window下动态库的名称为(.dll)

编写一个共享库

举一个例子

func1.c

void str(char *str){
	printf("%s\n",str);
}

func2.c

void data(int a){
	printf("%d\n",a);
}

然后用

gcc -c func1.c func2.c

生成.o文件

Linux下的.o文件就相当于Window下的.obj文件

他们都是对象文件

然后再用

gcc -shared -fpic -o func.so func1.o func2.o

生成一个func.so的共享库文件

编译目标文件时使用gcc的-fPIC选项,产生位置无关代码,以便加载到任何地址

-shared 生成共享目标文件。通常用在建立共享库时

然后用

ls

查看时,就会发现多了一个func.so的动态库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEvczDpa-1587793310590)(http://besthpy.top/blog/20190527/nXJ74BEwR5sq.JPG)]

动态库的静态调用

main.c

#include<stdio.h>
extern void str(char *str1);	//引用别的文件里面的函数必须要的声明
extern void data(int);
int main(void){
	str("hello");
	data(123456);
}

引用方式

注意一定要加 ./

gcc main.c ./func.so
./a.out

结果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LTsmrgjB-1587793310593)(http://besthpy.top/blog/20190527/9Lj2LGu5VXiX.JPG)]

动态库的动态加载

动态库的静态加载一般需要以下的几个函数

必须的头文件<dlfcn.h>

几个常用的函数

dlopen
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);

filename:要加载的共享文件名;NULL打开当前执

行文件

flag:RTLD_LAZY,加载对象的符号在被调用时解

析;RTLD_NOW,立即解析所有符号;RTLD_GLOBAL,与前两个任何一个 “或”导出所有符号

成功返回指针;失败返回NULL;

dlsym
#include <dlfcn.h>
void *dlsym(void *handle, char *symbol);

handle:dlopen返回的句柄指针

symbol:包含符号名称的字符串

成功返回指向符号的指针;失败返回NULL;

dlerror
#include <dlfcn.h>
const char *dlerror(void);

返回描述错误的字符串;否则返回NULL;

下面是一个动态加载的例子

在上面的基础上

dl.c

#include<dlfcn.h>
#include<stdio.h>
main(){
	void *handle=dlopen("./func.so",RTLD_NOW);	//返回的是一个指向动态
	//库的指针
	//创建了两个分别只想对应的函数的指针
	void (*test1)(char *) =dlsym(handle,"str");
	void (*test2)(int )=dlsym(handle,"data");
	//调用这两个指针
	(*test1)("hello!");
	test2(123456);
	//最后关闭这个指向动态库的指针
	dlclose(handle);
}

使用的命令

gcc dl.c -ldl

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6GQts1d5-1587793310596)(http://besthpy.top/blog/20190527/splOUcWmkdam.JPG)]

命令工具
nm命令

列出编入目标文件或二进制文件的所有符号

查看程序调用什么函数

查看一个给定的库或者目标文件是否提供了所需函数

语法:nm [options] file

常用的选项

选项 作用
-c 将符号名转换为用户级的名字
-s 当用于存档(.a)文件时,输出把符号名映射到定义该符号的模块或成员名的索引
-u 只显示未定义的符号——在被检查的文件外部定义的符号
-l 使用调试信息输出定义每个符号的行号,或者未定义符号的重定位项

一个例子

test.c

#include<stdio.h>
#include"test.h"
void print(){
	printf("rainy days\n");
}

main.c

#include"test.h"
int main(){
	print();
	return 0;
}

test.h

void print();

然后再用nm命令查看一下

一开始我们没有链接的时候

是什么都没有的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AHWzzXGW-1587793310597)(http://besthpy.top/blog/20190522/aPih8FUwHVJ4.png?imageslim)]

然后我们把这三个文件连接起来

gcc -c test.c main.c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cvmOLCqj-1587793310599)(http://besthpy.top/blog/20190522/HHRDk6RKNjgg.png?imageslim)]

ar命令(静态库)

创建高度结构化的存档文件,通常用来创建静态库

语法: ar [-]{dmpqrtx} [member] archive

选项 描述
-c 存档文件不存在则创建而不发出警告
-s 常见或升级从符号到定义他们的成员之间的交叉索引映射表
-r 向存档文件插入files,替换已有的任何同名成员。新成员添加到存档文件的末尾
-q files添加到存档文件的末尾而不检查是否进行替换

ar 最常见的就是建立一个静态库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uZKxPgIA-1587793310600)(http://besthpy.top/blog/20190522/yg8AJPge1B5i.png?imageslim)]

然后下面举一个使用的例子

test_program.c(用来使用这个静态库)

#include<stdio.h>
extern void print();	//必须的头文件,使用别的文件的函数时,必须要的语句
int main(){
        print();
}

gcc test_program.c 1.a(固定的格式)

gcc 目标程序 使用的静态库

代码截图如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kzzK6sOH-1587793310602)(http://besthpy.top/blog/20190522/XAVLSUjnjRX1.png?imageslim)]

资料引用

Linux的.a、.so和.o文件-Vincent乐

声明 本文资料来源于网络,以上图文,贵在分享,版权归原作者以及原出处一切,内容为作者观念,并不代表本人附和其观念和对齐真实性负责,如伤害到您的利益,请您在评论下方留言

Linux的编程库的静-动态链接的实现过程

上一篇:Oracle 中如何手工提交Cluster Table的事务


下一篇:java.sql.SQLException: [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序解决方法