进程的虚拟地址空间

上传人:ji****72 文档编号:39546309 上传时间:2018-05-17 格式:DOCX 页数:26 大小:74.28KB
返回 下载 相关 举报
进程的虚拟地址空间_第1页
第1页 / 共26页
进程的虚拟地址空间_第2页
第2页 / 共26页
进程的虚拟地址空间_第3页
第3页 / 共26页
进程的虚拟地址空间_第4页
第4页 / 共26页
进程的虚拟地址空间_第5页
第5页 / 共26页
点击查看更多>>
资源描述

《进程的虚拟地址空间》由会员分享,可在线阅读,更多相关《进程的虚拟地址空间(26页珍藏版)》请在金锄头文库上搜索。

1、进程的虚拟地址空间进程的虚拟地址空间 昨晚看到了深夜,终于对进程的虚拟地址空间有了个大致的了解,很激动,也很欣慰。回头想来,一个程序员,真的应该知道这些知识,否则还真不太称职。首先告诉大家,我后面提到的这些知识在windows 核心编程中都有,强烈建议大家把这本书翻翻,我相信会对你的编程境界拔高好几个层次的。可是我最近没那么多时间,因此就只能了解个大概,然后等今后闲暇时再看这本书吧。昨天我媳妇还反复和我说:学东西必须要有选择,不能对 IT 行业的所有知识乱学习,而且不要学那种实际意义不大的知识或是容易被淘汰的知识。其实她说的蛮对的,但是我要说,有关windows 核心编程里的知识永远都不会过时

2、,因为它侵入到底层和内部了,就像 C+,你觉得会过时吗?就像 windows 永远不会被淘汰一样,呵呵。下面我就来粗略的说说我了解的一些基本知识:32 位机器,每个程序有位机器,每个程序有 4G 的虚拟地址空间。的虚拟地址空间。大致分为 4 块,从低地址到高地址依次是:NULL 区,用户区,隔离区,核心区区,用户区,隔离区,核心区。用户私有的数据都在用户区(当然这个区里又可以细分,其中也包括一部分可以共享的内容),系统内核等东西都在核心区。总体来说,A 进程的虚拟地址空间中的内容和进程的虚拟地址空间中的内容和 B 进程相比,进程相比,只有各自的用户区不一致。只有各自的用户区不一致。通常用户区中

3、,进程又会将 exe 文件(由头数据和段数据组成)中定义的代码段、堆栈段、数据段等各个段映射到用户区的特定段映射到用户区的特定不同部位不同部位。对于这部分区域,用户需要用 VirtualAlloc 先为自己预留后再提交,最后在自己的页面被 cpu 访问时再从 exe 映像中将数据加载到主存,然后将虚拟地址映射为主存的物理地址。基本上这样就可以了,至于系统如何进行页面的管理以及地址映射如何实现等细节请大家再参考别的文献。我本以为很复杂呢,结果写出来,就这么一小段,呵呵,看来是高估了自己理解的东西了,呵呵。下面贴出我看的一些资料:虚拟存储器是一个抽象概念,它为每一个进程提供了一个假象,好像每个进程

4、都在独占的使用主存。每个进程看到的存储器都是一致的,称之为虚拟地址空间。 每个进程看到得虚拟地址空间有大量准确定义的区(area)构成,每个区都有专门的功能。从最低的地址看起:程序代码和数据:代码是从同一固定地址开始,紧接着的是和 C 全局变量相对应的数据区。 (应该就是所谓的静态存储空间) 堆:代码和数据区后紧随着的是运行时堆。作为调用 malloc 和 free 这样的 C 标准库函数,堆可以在运行时动态的扩展和收缩。(应该就是所谓的动态存储区) 共享库:在地址空间的中间附近是一块用来存放像 C 标准库和数学库这样共享库的代码和数据的区域。(C 标准库函数的指令,连接阶段把他们加入到编译后

5、的程序) 栈:位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一样每次我们从函数返回时,栈就会收缩。 内核虚拟存储器:内核是操作系统总是驻留在存储器中的部分。地址空间顶部的四分之一部分是为内核预留的。(系统函数?这里说的 UNIX系统,不知道 windows 下是不是这样的?) 今天大多数计算机的字长都是 32 字节,这就限制了虚拟地址空间为 4 千兆字节(4GB)引言 Windows 的内存结构是深入理解 Windows 操作系统如何运作的最关键之所在,通过对内存结构的认识可清楚地了解诸如进程间数据的共享、对内存进行有效的管理等问题,从而能够在程序设计时使程序以更加有效的方

6、式运行。Windows 操作系统对内存的管理可采取多种不同的方式,其中虚拟内存的管理方式可用来管理大型的对象和结构数组。在 Windows 系统中,任何一个进程都被赋予其自己的虚拟地址空间,该虚拟地址空间覆盖了一个相当大的范围,对于 32 位进程,其地址空间为232=4,294,967,296 Byte,这使得一个指针可以使用从 0x00000000 到0xFFFFFFFF 的 4GB 范围之内的任何一个值。虽然每一个 32 位进程可使用4GB 的地址空间,但并不意味着每一个进程实际拥有 4GB 的物理地址空间,该地址空间仅仅是一个虚拟地址空间,此虚拟地址空间只是内存地址的一个范围。进程实际可

7、以得到的物理内存要远小于其虚拟地址空间。进程的虚拟地址空间是为每个进程所私有的,在进程内运行的线程对内存空间的访问都被限制在调用进程之内,而不能访问属于其他进程的内存空间。这样,在不同的进程中可以使用相同地址的指针来指向属于各自调用进程的内容而不会由此引起混乱。下面分别对虚拟内存的各具体技术进行介绍。地址空间中区域的保留与释放地址空间中区域的保留与释放在进程创建之初并被赋予地址空间时,其虚拟地址空间尚未分配,处于空闲状态。这时地址空间内的内存是不能使用的,必须首先通过 VirtualAlloc()函数来分配其内的各个区域,对其进行保留。LPVOID VirtualAlloc(LPVOID lp

8、Address, DWORD dwSize, DWORD flAllocationType,DWORD flProtect);其参数 lpAddress 包含一个内存地址,用于定义待分配区域的首地址。通常可将此参数设置为 NULL,由系统通过搜索地址空间来决定满足条件的未保留地址空间。这时系统可从地址空间的任意位置处开始保留一个区域,而且还可以通过向参数 flAllocationType 设置 MEM_TOP_DOWN 标志来指明在尽可能高的地址上分配内存。如果不希望由系统自动完成对内存区域的分配而为lpAddress 设定了内存地址(必须确保其始终位于进程的用户模式分区中,否则将会导致分配的

9、失败),那么系统将在进行分配之前首先检查在该内存地址上是否存在足够大的未保留空间,如果存在一个足够大的空闲区域,那么系统将会保留此区域并返回此保留区域的虚拟地址,否则将导致分配的失败而返回NULL。这里需要特别指出的是,在指定 lpAddress 的内存地址时,必须确保是从一个分配粒度的边界处开始。一般来说,在不同的 CPU 平台下分配粒度各不相同,但目前所有 Windows 环境下的 CPU 如 x86、32 位 Alpha、64 位 Alpha 以及 IA-64 等均是采用 64KB的分配粒度。如果保留区域的起始地址没有遵循从 64KB 分配粒度的边界开始之一原则,系统将自动调整该地址到最

10、接近的 64K 的倍数。例如,如果指定的lpAddress 为 0x00781022,那么此保留区域实际是从 0x00780000 开始分配的。参数 dwSize 指定了保留区域的大小。但是系统实际保留的区域大小必须是CPU 页面大小的整数倍,如果指定的 dwSize 并非 CPU 页面的整数倍,系统将自动对其进行调整,使其达到与之最接近的页面大小整数倍。与分配粒度一样,对于不同的 CPU 平台其页面大小也是不一样的。在 x86 平台下,页面大小为 4KB,在 32 位 Alpah 平台下,页面大小为 8KB。在使用时可以通过GetSystemInfo()来决定当前主机的页面大小。参数 flA

11、llocationType 和flProtect 分别定义了分配类型和访问保护属性。由于 VirtualAlloc()可用来保留一个区域也可以用来占用物理存储器,因此通过 flAllocationType 来指定当前是要保留一个区域还是要占用物理存储器。其可能使用的内存分配类型有:分配类型 类型说明MEM_COMMIT为特定的页面区域分配内存中或磁盘的页面文件中的物理存 储MEM_PHYSICAL 分配物理内存(仅用于地址窗口扩展内存)MEM_RESERVE保留进程的虚拟地址空间,而不分配任何物理存储。保留页 面可通过继续调用 VirtualAlloc()而被占用MEM_RESET 指明在内存

12、中由参数 lpAddress 和 dwSize 指定的数据无效MEM_TOP_DOWN在尽可能高的地址上分配内存(Windows 98 忽略此标志)MEM_WRITE_WATCH必须与 MEM_RESERVE 一起指定,使系统跟踪那些被写入分配 区域的页面(仅针对 Windows 98)分配成功完成后,即在进程的虚拟地址空间中保留了一个区域,可以对此区域中的内存进行保护权限许可范围内的访问。当不再需要访问此地址空间区域时,应释放此区域。由 VirtualFree()负责完成。其函数原型为:BOOL VirtualFree(LPVOID lpAddress,DWORD dwSize,DWORD

13、dwFreeType );其中,参数 lpAddress 为指向待释放页面区域的指针。如果参数 dwFreeType指定了 MEM_RELEASE,则 lpAddress 必须为页面区域被保留时由VirtualAlloc()所返回的基地址。参数 dwSize 指定了要释放的地址空间区域的大小,如果参数 dwFreeType 指定了 MEM_RELEASE 标志,则将 dwSize设置为 0,由系统计算在特定内存地址上的待释放区域的大小。参数dwFreeType 为所执行的释放操作的类型,其可能的取值为 MEM_RELEASE和 MEM_DECOMMIT,其中 MEM_RELEASE 标志指明要

14、释放指定的保留页面区域,MEM_DECOMMIT 标志则对指定的占用页面区域进行占用的解除。如果VirtualFree()成功执行完成,将回收全部范围的已分配页面,此后如再对这些已释放页面区域内存的访问将引发内存访问异常。释放后的页面区域可供系统继续分配使用。下面这段代码演示了由系统在进程的用户模式分区内保留一个 64KB 大小的区域,并将其释放的过程:/ 在地址空间中保留一个区域LPBYTE bBuffer = (LPBYTE)VirtualAlloc(NULL, 65536, MEM_RESERVE, PAGE_READWRITE);/ 释放已保留的区域VirtualFree(bBuffe

15、r, 0, MEM_RELEASE);flProtect 页面保护属性页面保护属性我们可以给每个已分配的物理存储页指定不同的页面保护属性。表 13-3 列出了 所有的页面保护属性。表表 13-3 内存页面保护属性内存页面保护属性保护属性描 述PAGE_NOACCESS试图读取页面、写入页面或执行页面中的 代码将引发访问违规PAGE_READONLY试图写入页面或执行页面中的代码将引发 访问违规PAGE_READWRITE试图执行页面中的代码将引发访问违规PAGE_EXECUTE试图读取页面或写入页面将引发访问违规PAGE_EXECUTE_READ试图写入页面将引发访问违规PAGE_EXECUT

16、E_READWRITE对页面执行任何操作都不会引发访问违规PAGE_WRITECOPY试图执行页面中的代码将引发访问违规。 试图写入页面将使系统为进程单独创建一 份该页面的私有副本(以页交换文件为后备 存储器)PAGE_EXECUTE_WRITECOPY对页面执行任何操作都不会引发访问违规。 试图写入页面将使系统为进程单独创建一 份该页面的私有副本(以页交换文件为后备 存储器)一些恶意软件将代码写入到用于数据的内存区域(比如线程栈上),通过这种方式让应用程序执行恶意代码。Windows 的数据执行保护(Data Execution Protection,后面简称为 DEP)特性提供了对此类恶意攻击的防护。如果启用了 DEP,那么只有对那些真正需要执行代码的内存区域,操作系统才会使用 PAGE_EXECUTE_*保护属性。其他保护属性(最常见的就是 PAGE_READWRITE)用于只应该存放数据的内存区域(比如线程栈和应用程序的堆 )。如果 CPU 试图执行某个页面中的代码,而该页又没有 PAGE_EXECUTE_*保护属性,那么 CPU 会抛出访问违规异

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号