当前位置: 首页 > news >正文

windows DLL技术-DLL概述

动态链接库 (DLL) 是一个模块,其中包含可由另一个模块 (应用程序或 DLL) 使用的函数和数据。

DLL 可以定义两种类型的函数:导出函数和内部函数。 导出的函数旨在由其他模块调用,以及从定义它们的 DLL 中调用。 内部函数通常只能从定义内部函数的 DLL 中调用。 尽管 DLL 可以导出数据,但其数据通常仅由其函数使用。 但是,没有什么可以阻止另一个模块读取或写入该地址。

DLL 提供了一种模块化应用程序的方法,以便可以更轻松地更新和重复使用其功能。 当多个应用程序同时使用相同的功能时,DLL 还有助于减少内存开销,因为尽管每个应用程序都接收自己的 DLL 数据副本,但应用程序会共享 DLL 代码。

windows 应用程序编程接口 (API) 作为一组 DLL 实现,因此使用 Windows API 的任何进程都使用动态链接,在实际开发中,DLL是最广泛使用的技术之一,许多公司的产品都会以DLL的形式发布。

静态链接库和动态链接库

在windows 体系中,库分为静态库(LIB)和动态库(DLL),它们都是代码共享的一种方式,但二者有一定的区别;同时由于动态库也生成Lib文件,还支持静态调用和动态调用,所以在讲解动态库之前,需要对这两种库进行一个简单的说明:

动态链接库的静态链接和动态链接

  • 在 加载时动态链接中,模块显式调用导出的 DLL 函数,就像它们是本地函数一样。 这要求将模块与包含函数的 DLL 的导入库链接。 导入库为系统提供加载 DLL 所需的信息,并在加载应用程序时查找导出的 DLL 函数;
  • 在 运行时动态链接中,模块使用 LoadLibrary 或 LoadLibraryEx 函数在运行时加载 DLL。 加载 DLL 后,模块调用 GetProcAddress 函数以获取导出的 DLL 函数的地址。 该模块使用 GetProcAddress 返回的函数指针调用导出的 DLL 函数。 这样就不需要导入库了;

静态链接库简介

windows 平台的编译是指将代码文件编码转换为中间文件(使用cl.exe),链接则是将Obj文件链接为可执行文件(使用link.exe)。

静态链接库是代码进行编译,但是没有实际链接;动态链接库则经过了编译和链接,所以静态库在实际使用的时候,相当于将代码放到项目中;而DLL则是引用其他可执行文件的接口。

很多时候,静态库也作为软件厂商发布产品的一种方式,因为静态库不涉及代码保护,而DLL则设计代码的动态调用。

注意: 静态库生成lib是源代码文件转换为obj文件的集合,里面是有可执行代码的;动态库的lib文件则是符号文件,本身不包含可执行的代码,故仅从.lib的后缀名不能确认它是静态库还是动态库,当然它内部的格式可以区分这两种类型。

动态链接的类型

在 DLL 中调用函数有两种方法:

  • 在 加载时动态链接中,模块显式调用导出的 DLL 函数,就像它们是本地函数一样。 这要求将模块与包含函数的 DLL 的导入库链接。 导入库为系统提供加载 DLL 所需的信息,并在加载应用程序时查找导出的 DLL 函数;
  • 在 运行时动态链接中,模块使用 LoadLibrary 或 LoadLibraryEx 函数在运行时加载 DLL。 加载 DLL 后,模块调用 GetProcAddress 函数以获取导出的 DLL 函数的地址。 该模块使用 GetProcAddress 返回的函数指针调用导出的 DLL 函数。 这样就不需要导入库了;
DLL 和内存管理

加载 DLL 的每个进程都会将其映射到其虚拟地址空间。 进程将 DLL 加载到其虚拟地址后,可以调用导出的 DLL 函数。

系统维护每个 DLL 的每个进程引用计数。 当线程加载 DLL 时,引用计数将增加 1。 当进程终止时,或者当引用计数变为零 (运行时动态链接仅) 时,将从进程的虚拟地址空间中卸载 DLL。

与任何其他函数一样,导出的 DLL 函数在调用它的线程的上下文中运行。 因此,以下条件适用:

  • 调用 DLL 的进程线程可以使用 DLL 函数打开的句柄。 同样,调用进程的任何线程打开的句柄都可以在 DLL 函数中使用;
  • DLL 使用调用线程的堆栈和调用进程的虚拟地址空间;
  • DLL 从调用进程的虚拟地址空间分配内存;
动态链接库的优势

动态链接比静态链接具有以下优势:

  • 在同一基址加载同一 DLL 的多个进程在物理内存中共享该 DLL 的单个副本。 这样做可节省系统内存并减少交换;
  • DLL 中的函数发生更改时,只要函数参数、调用约定和返回值不更改,就不需要重新编译或重新链接使用它们的应用程序。 相比之下,静态链接对象代码要求在函数更改时重新链接应用程序;
  • DLL 可以提供市场后支持。 例如,可以修改显示驱动程序 DLL 以支持应用程序最初交付时不可用的显示器;
  • 以不同编程语言编写的程序可以调用同一 DLL 函数,只要这些程序遵循该函数使用的相同调用约定。 调用约定 (如 C、Pascal 或标准调用) 控制调用函数必须将参数推送到堆栈的顺序、函数还是调用函数负责清理堆栈,以及是否在寄存器中传递任何参数。 

使用 DLL 的一个潜在缺点是应用程序不是自包含的;这取决于是否存在单独的 DLL 模块。 如果进程需要未在进程启动时找到的 DLL,系统会使用加载时动态链接终止进程,并向用户提供错误消息。 在这种情况下,系统不会使用运行时动态链接终止进程,但程序无法使用缺少的 DLL 导出的函数。

http://www.lryc.cn/news/466513.html

相关文章:

  • C++ —— 实现一个日期类
  • Java全栈经典面试题剖析5】JavaSE高级 -- 集合
  • python中如何获取对象信息
  • 逐行讲解transformers中model.generate()源码
  • 小白对时序数据库的理解
  • 打开游戏提示丢失(或找不到)XINPUT1_3.DLL的多种解决办法
  • netty的网络IO模型
  • 电子木鱼小游戏小程序源码系统 带完整的安装代码包以及搭建部署教程
  • 支付域——交易系统设计
  • IBus 和 Fcitx 框架下的rime输入法引擎
  • Java基础-JVM
  • 集成学习:投票法、提升法、袋装法
  • 波浪理论、江恩理论、价值投资的结合
  • LRDDR4芯片学习(三)——命令和时序
  • 【趣学C语言和数据结构100例】
  • linux卸载数据库(最为完整的卸载方式)
  • H7-TOOL的LUA小程序教程第15期:电压,电流,NTC热敏电阻以及4-20mA输入(2024-10-21,已经发布)
  • 使用梧桐数据库进行销售趋势分析和预测
  • SQLITE排序
  • python的文件操作
  • 群晖通过 Docker 安装 MySQL
  • 同程旅行面经
  • 【贪心算法】(第八篇)
  • 立即调用的函数表达式(IIFE)
  • YOLOv11改进-卷积-引入小波卷积WTConv 解决多尺度小目标问题
  • flask 接口还在执行中,前端接收到接口请求超时,解决方案
  • 探索 Python 中的 XML 转换利器:xml2dict
  • dbt-codegen: dbt自动生成模板代码
  • springboot057洗衣店订单管理系统(论文+源码)_kaic
  • 南大通用(GBase 8s)数据库在 Spring Boot 中使用 Flyway