Windows核心编程_动态链接库_DLL基础_DLL与进程的地址空间

本文主要是介绍Windows核心编程_动态链接库_DLL基础_DLL与进程的地址空间,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通常创建一个DLL要比建立一个应用程序容易,因为DLL包含一组可以被任何应用所使用的自治(autonomous)函数。在DLL中通常没有支持处理消息循环或创建窗口的代码。一个DLL只是一组源代码模块的集合。其中每个模块包含应用程序(可执行文件)或另一个DLL将要调用的一组函数。当所有的源代码文件编译后,就像应用程的可执行文件那样被链接程序所链接。然而,对于一个DLL,必须要为链接程序设定DLL开关选项。该选项使得链接程序向生成的DLL文件映像发出略有差异的信息,这样,操作系统装载程序就可以将该文件映像识别为一个DLL,而不是应用程序。
在应用程序(或另一个DLL)可以调用DLL中的函数之前,DLL的文件映射必须映射到调用进程的地址空间。可以采用两种方法来完成这项操作:隐式的装载时链接或显示的运行时链接,隐式链接在本章后续部分加以讨论,显示链接将在第20章中进行讨论。
一旦DLL的文件映射到调用进程的地址空间,则DLL中的函数对于运行在该进程内的所有线程都是可用的。实际上DLL几乎失去了它作为DLL的所有特征标志。对于进程中的线程而言,DLL的代码和数据开起来就像是恰好存在于进程地址空间中的额外代码和数据。当一个线程调用DLL函数时,该函数查看线程的栈以检索被传递的参数,并且将线程的栈空间用于它所需要的任意局部变量。另外,被DLL中的函数代码所创建的任何对象都属于调用它的线程或进程——一个DLL并不拥有任何元素。
例如,如果DLL中的一个函数所调用VirtualAlloc,则将从调用线程的进程地址空间中保留该地址空间的区域。如果后来从进程的地址空间中取消DLL的映射,则该地址空间的区域仍然会保留,因为系统并没有跟踪记录这样一个事实:DLL中的函数保留着该区域。被保留的地址空间区域是属于调用进程的,只有当一个线程调用VirtualFree函数或该进程终止时,该保留区域才会释放。
一个可执行文件中的全局变量和静态变量不能被该可执行文件的多个运行实例所共享。在Windows 98中,是通过当可执行文件映射到进程的地址空间时,为该文件的全局变量和静态变量分配存储空间的机制来保证这一点的;而在Windows 2000中,则是通过第13章中讨论的写时复制(copy-on-write)机制来加以保证的。一个DLL中的全局变量和静态变量是以相同的方式处理的。当一个进程把一个DLL的映射文件映射到其地址空间时,系统将同时创建全局数据变量和静态数据变量的实例。
注意:需要引起重视的是,一个单独的地址空间是由一个可执行模块和若干个DLL模块组成的。其中的一些模块可以链接到一个静态版本的C/C++运行时库,还有一些模块可能链接到一个DLL版本的C/C++运行时库,而另外一些模块(如果不是用C/C++编写的)可能根本就不需要C/C++运行时库。许多开发人员都存在一个错误的认识,因为他们忘记了若干个C/C++运行时库可能会存在于一个单一的地址空间中。研究下面的代码:

PVOID DLLFunc()
{// Allocate bloc from DLL's C/C++ run-time heapreturn malloc(100);
}VOID EXEFunc()
{PVOID pv = DLLFunc();// Access the storage pointed to by pv...// Assumes that pv is in EXE's C/C++ run-time heapfree(pv);
}

那么你是怎样考虑的呢?上述代码能够正确运行吗?DLL中的函数所分配的块是否被EXE中的函数所释放?答案是:可能会是这样!因为上述代码并没有提供足够的信息。如果EXE和DLL这两者都链接到DLL版本的C/C++运行时库,则对free调用将会失败。我曾多次见过开发人员编写出类似的代码,结果是毁了代码。
有一个简单的方法可以解决这个问题。当一个模块提供了分配内存的函数时,该模块必须同时提供一个释放内存的函数。重写上述代码如下:

PVOID DLLFunc()
{// Allocate bloc from DLL's C/C++ run-time heapreturn malloc(100);
}VOID DLLFreeFunc(PVOID pv)
{// Free bloc form DLL's C/C++ run-time heapreturn free(pv);
}VOID EXEFunc()
{PVOID pv = DLLFunc();// Access the storage pointed to by pv...// Assumes that pv is in EXE's C/C++ run-time heapfree(pv);
}

经过重写后的代码是正确的,它总是可以正确地执行。当编写一个模块时,不要忘记其它模块中的那些函数,它们甚至可能不是用C/C++编写的,因此可能不会使用malloc和free函数进行内存分配。注意不要在代码中设定这些假设条件。顺便提及,当调用malloc和free函数时,该结论对于C++的new和delete操作符也是相同的。

这篇关于Windows核心编程_动态链接库_DLL基础_DLL与进程的地址空间的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1036067

相关文章

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Ubuntu固定虚拟机ip地址的方法教程

《Ubuntu固定虚拟机ip地址的方法教程》本文详细介绍了如何在Ubuntu虚拟机中固定IP地址,包括检查和编辑`/etc/apt/sources.list`文件、更新网络配置文件以及使用Networ... 1、由于虚拟机网络是桥接,所以ip地址会不停地变化,接下来我们就讲述ip如何固定 2、如果apt安

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Windows设置nginx启动端口的方法

《Windows设置nginx启动端口的方法》在服务器配置与开发过程中,nginx作为一款高效的HTTP和反向代理服务器,被广泛应用,而在Windows系统中,合理设置nginx的启动端口,是确保其正... 目录一、为什么要设置 nginx 启动端口二、设置步骤三、常见问题及解决一、为什么要设置 nginx

查询SQL Server数据库服务器IP地址的多种有效方法

《查询SQLServer数据库服务器IP地址的多种有效方法》作为数据库管理员或开发人员,了解如何查询SQLServer数据库服务器的IP地址是一项重要技能,本文将介绍几种简单而有效的方法,帮助你轻松... 目录使用T-SQL查询方法1:使用系统函数方法2:使用系统视图使用SQL Server Configu

使用Java实现获取客户端IP地址

《使用Java实现获取客户端IP地址》这篇文章主要为大家详细介绍了如何使用Java实现获取客户端IP地址,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 首先是获取 IP,直接上代码import org.springframework.web.context.request.Requ

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

C++实现获取本机MAC地址与IP地址

《C++实现获取本机MAC地址与IP地址》这篇文章主要为大家详细介绍了C++实现获取本机MAC地址与IP地址的两种方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实际工作中,项目上常常需要获取本机的IP地址和MAC地址,在此使用两种方案获取1.MFC中获取IP和MAC地址获取