2021-01-04

动态库的制作和使用

lib库名.so

  1. 将所有要打包的动态库的源文件编译为目标文件(与位置无关的目标文件?)
    gcc -c -fPIC t*.c 将所有t 开头 的.c 文件打包生成与位置无关的.o 文件
  2. 将第一步中生成的目标文件打包成为动态库
    gcc -shared -o libt_math.so *.o
  3. 使用动态库链接生成可执行文件
    gcc main.c -L. -lt_math
    注意: 这一步使用的是静态连接器,当识别为动态库时,只是check 一下其中有没有需要的函数 没有则会报错。
    然后执行./a.out 会有error :
    显示 libt_math.so cant open 找不到这个文件
    产生这个error 的原因是动态连接器到不到文件

处理方法

ldd a.out : 查看 a.out 在执行时,需要依赖那些动态库
普通的c 程序依赖的库如下
linux-vdso.so.1 => (0x00007ffd769f4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fee7137b000)
/lib64/ld-linux-x86-64.so.2 (0x00007fee71745000)
libt_math.so =》 not found
表示动态链接器无法找到这个动态库

告知动态连接器这个库文件的位置:
1.export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
冒号分隔符分隔多条路径
2. 动态连接器默认的搜索路径是 /lib 或者是 /usr/lib

静态库和动态库的区别

  1. 使用静态库生成的可执行文件不再依赖静态库,
  2. 使用动态库生成的可执行文件,在执行时依赖动态库。
  3. 使用动态库生成的可执行文件,执行时,依赖的动态库由系统管理,不需用户的干预。由系统直接加载依赖的动态库。

将动态库加载到内存执行的叫做加载器, 加载器中包含一个动态连接器。

动态连接器是一个软件。 向外提供了服务接口。
用户可以调用动态连接器的接口,按需加载。

动态加载

动态连接器给用户提供了什么服务? 服务的接口是什么?
dlopen(3) dlcolse(3) dlerror(3) dlsym(3)

#include <dlfcn.h>

   void *dlopen(const char *filename, int flags);
   功能: 
   参数:filename  动态库的路径名字
   		flags :  RTLD_LAZY  懒绑定
                     RTLD_NOW  立即加载
   返回值: 返回一个地址
   成功: 非NULL
   失败 : NULL   可以使用dlerror(3) 来获取函数失败的错误诊断信息
   
   void *p   void* 表示返回一个不访问的地址
   char *q  char* 表示返回一个地址,这个地址中放了一个char 类型的数据
   

   int dlclose(void *handle);
   如果引用计数减到0,则将共享库卸载
   参数 : 
   handle 指定了要操作的共享库的地址

char *dlerror(void);
返回值:
返回描述错误的字符串
Link with -ldl.

void *dlsym(void *handle, const char *symbol);
功能 获取指定的符号加载到内存的地址
参数
handle dlopen 打开共享库文件的返回值
symbol (函数的名称)
返回值
符号的地址

code :

#include <stdio.h>
#include <dlfcn.h>

typedef int (*f_t)(int, int);
int main(int argc, char * argv[])
{ 
	void *handle = dlopen(argv[1],RTLD_NOW);
	if (NULL == handle)
	{
		printf("dlopen error ....\n");
		printf("%s \n",dlerror());
		return -1;
	}
	printf("dlopen success ...\n");
	f_t f = (f_t)dlsym(handle, "sub");
	if (NULL == f)
		printf("dlsym error : %s\n",dlerror());
	printf("sub(3-2)= %d\n",f(3,2));

	dlclose(handle);
	return 0;
}

库文件源码:

> #include "lib/t_math.h"
> 
> int sub (int a, int b) { 	return (a-b); }
> 
> int mul (int a, int b) { 	return (a*b); }
ldd dynamic
	linux-vdso.so.1 =>  (0x00007ffd2dbc7000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f78a1c20000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f78a1856000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f78a1e24000)

可以发现 编译出来的 dynamic 链接的库文件中有
libdl.so.2 这个就是加载器的库文件 通过这个库 可以动态加载动态库

nm  dynamic
 U dlclose@@GLIBC_2.2.5
                 U dlerror@@GLIBC_2.2.5
                 U dlopen@@GLIBC_2.2.5
                 U dlsym@@GLIBC_2.2.5

其中没有 sub 的符号,但是有动态连接器的函数符号,通过这些函数,动态加载libt_math.so

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值