[Linux]------动静态库的模拟实现和简单使用
创始人
2024-04-07 00:34:46
0

文章目录

  • 前言
  • 一、概念
  • 二、生成静态库
    • 生成
    • 发布
  • 三、生成动态库
    • 发布
  • 四、使用库
    • 1. 使用静态库
      • 系统头文件路径
      • 系统库文件路径
      • 使用库文件和头文件
      • 指定路径搜索头文件
      • 卸载库
    • 2. 使用动态库
      • 动态库的运行搜索路径
      • 进程为什么找不到对应的动态库
  • 总结


前言


正文开始!

一、概念

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静
    态库
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文
    件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个
    过程称为动态链接(dynamic linking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚
    拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间

安装C语言静态库

yum install -y glibc -static

二、生成静态库

首先我们库里面是不需要包含main函数的!

链接:就是把所有的.o链接形成一个可执行程序!!!

如果我把我的所有的.o给别人,别人能链接使用吗??—> 当然是可以的!

测试程序

/mymath.h//
#pragma once
#include
#include
//[from,to]-->累加-->result--->return
extern int addToVal(int from,int to);/mymath.c//
#include"mymath.h"
int addToVal(int from,int to)
{assert(from<=to);int result=0;for(int i=from;i<=to;i++){result+=i;}return result;
}/myprint.h//
#pragma once
#include
#include
extern void Print(const char* msg); /myprint.c//
#include"myprint.h"
void Print(const char* msg)
{printf("%s : %lld\n",msg,(long long)time(NULL));
}

生成

命令

ar -rc [文件]
(ar是gnu的归档工具,rc表示(replace and create))

libmymath.a:mymath.o myprint.oar -rc libmymath.a mymath.o myprint.o
mymath.o:mymath.cgcc -c mymath.c -o mymath.o -std=c99
myprint.o:myprint.cgcc -c myprint.c -o myprint.o -std=c99
.PHONY:clean
clean:rm -f *.o *.a

在这里插入图片描述

发布

问题:我们在用库的时候需要什么东西呢??

答:库文件和头文件!!—>就可以给别人使用了

命令

.PHONY:static
static:mkdir -p lib-static/lib;\mkdir -p lib-static/include;\cp *.a lib-static/lib;\cp *.h lib-static/include

在这里插入图片描述

三、生成动态库

  • shared: 表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)—>以后编译的源代码无论生成的.o文件在哪里都可以执行
  • 库名规则:libxxx.so
libmymath.so:mymath.o myprint.ogcc -shared -o libmath.so mymath.o myprint.o
mymath.o:mymath.cgcc -fPIC -c mymath.c -o mymath.o -std=c99
myprint.o:myprint.cgcc -fPIC -c myprint.c -o myprint.o -std=c99.PHONY:clean
clean:rm -rf *.o *.so

在这里插入图片描述

发布

.PHONY:dyl
dyl:mkdir -p lib-dyl/lib;\mkdir -p lib-dyl/include;\cp *.so lib-dyl/lib;\cp *.h lib-dyl/include

在这里插入图片描述

四、使用库

1. 使用静态库

#include"mymath.h"
#include"myprint.h"int main()
{int start=0;int end=100;int result=addToVal(start,end);printf("%d\n",result);Print("hello world");return 0;
}

首先我们先来回顾C语言头文件的搜索路径: “” <>

  1. 在当前路径下查找头文件
  2. 在系统头文件路径下查找头文件
  3. 指定路径头文件的搜索路径(-I(include) 你的头文件搜索路径 -L(link) 你的库路径 -l 具体哪一个库文件)

谁在头文件呢???—>编译器---->进程

在这里插入图片描述

系统头文件路径

ls /usr/include/

在这里插入图片描述

系统库文件路径

ls /lib64/

在这里插入图片描述

使用库文件和头文件

将自己的头文件和库文件,拷贝到系统路径下即可!!!(库的安装)

sudo cp lib-static/include/* /usr/include/
sudo cp lib-static/lib/* /usr/lib64/

在这里插入图片描述

其实我们之前没有用过任何第三方库!

gcc -l(指明我要链接的第三方库的名称)

在这里插入图片描述

但是不推荐这种做法,因为这种做法会污染系统的头文件和库文件!

指定路径搜索头文件

gcc mytest.c -o mytest -I ./lib-static/include/

在这里插入图片描述
虽然有错误,但并不是说头文件找不到了,现在还需要我们链接库文件!

gcc mytest.c -o mytest -I ./lib-static/include/ -L ./lib-static/lib/ -lmymath

在这里插入图片描述
在这里插入图片描述
如果安装到系统就没有这么麻烦了。

卸载库

sudo rm /usr/include/mymath.h
sudo rm /usr/include/myprint.h
sudo rm /lib64/libmymath.a

在这里插入图片描述

2. 使用动态库

第一种方法和静态库的使用一模一样:将自己的头文件和库文件,拷贝到系统路径下即可!!!

这里就不做演示了!

第二种指定路径包含头文件和库文件
在这里插入图片描述

但是我们运行程序去报错了!!

在这里插入图片描述
查看我们程序所依赖的库

ldd mytest

在这里插入图片描述
问题来了:编译的时候gcc所带的-I,-L,-l选项是给谁带的? ---->gcc

所以形成可执行程序后,与编译器gcc就没有任何关系了。

所以./mytest运行进程后,并没有告诉进程这个库链接在哪里!!

动态库的运行搜索路径

根据上面的问题,进程找不到对应的动态库!

  • 那么静态库的时候,怎么没有这个问题呢?–>形成可执行程序之后,已经把需要的代码拷贝进我的代码中!运行时不依赖你的库!—>不需要运行时查找了
  • 为什么动态库会有这个问题呢?—>程序和动态库是分开加载的!

那么如何解决找不到动态库的问题呢??
想办法让进城找到动态库即可!

  1. 动态库拷贝到系统路径下/lib64/ —>安装
  2. 通过导入环境变量的方式---->程序运行的时候,会在环境变量中查找自己需要的动态库路径(LD_LIBRARY_PATH)
  3. 系统配置文件来做
  4. 其他方式

通过导入环境变量的方式

echo LDLIBRARYPATHexportLDLIBRARYPATH=LD_LIBRARY_PATH export LD_LIBRARY_PATH=LDL​IBRARYP​ATHexportLDL​IBRARYP​ATH=LD_LIBRARY_PATH:[绝对路径]

在这里插入图片描述
在这里插入图片描述

这个解决办法重启Xshell就不可以了,因为Xshell默认重启后会还原环境变量!

系统配置文件来做

[root@localhost linux]# cat /etc/ld.so.conf.d/bit.conf
/root/tools/linux
[root@localhost linux]# ldconfig

在这里插入图片描述
查看还是发现没有我们需要链接的动态库

在这里插入图片描述

sudo ldconfig

现在我们就能找到动态库并且运行了
在这里插入图片描述
这个解决方法Xshell关闭后也不受影响!!

其他方式

sudo ln -s /home/hulu/2022_10_27/mklib/test/lib-dyl/lib/libmath.so /lib64/libmath.so

在这里插入图片描述

该方法就是在系统库创建了一个软链接!

在这里插入图片描述

进程为什么找不到对应的动态库

在这里插入图片描述


总结

(本章完)

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...