《windows核心编程》–Windows内存体结构(一)

13.1 进程虚拟地址空间

每个进程都有自己的专有地址空间,对32位进程来说,这个地址空间的大小为4GB,这是因为32位指针可以表示从0x00000000-0xffffffff的任意值。对64位进程来说则可以表示0x0000000000000000 到0xffffffffffffffff之间任一值。

因为每一个进程都有自己的专有地址空间,当进程中的各线程运行时,它们只访问属于该进程的内存。线程即看不到其他进程内容空间,也无法访问它们。

进程A可以在位于它地址空间内的0x12345678地址处存储一个数据结构,而进程B也可以 “自己的”地址空间存储一个0x12345678处的内存。当进程A访问0x12345678时他访问的是A的数据结构,进程 B访问0x12345678他访问的则是B的这块数据。进程A中的线程无法访问位于进程 B的地址空间内的数据结构,反之亦然 。

虽然应用程序有这么大的地址空间可用,但是要记住这只是虚拟地址空间----不是物理存储空间。这个地址空间只不过是一个内存地址区间。为了能够正常读写我们还需要把物理存储器分配或映射到相应地址空间,否则将导致访问违规。

13.2 虚拟地址空间的分区

进程的地址空间是如何划分的

分区 x86 32位 windows 3GB用户模式下的x86 32位windows x64 windows ia-64 64位windows
空指针赋值分区 0x00000000
0x0000FFFF
0x00000000
0x0000FFFF
0x00000000 00000000
0x00000000 0000FFFF
0x00000000 00000000
0x00000000 0000FFFF
用户模式分区 0x00010000
0x7FFFFFFFF
0x00010000
0xBFFFFFFFF
0x00000000 00010000
0x000007FF FFFFFFFF
0x00000000 00000000
0x000006FB FFFFFFFF
64 KB 禁入分区 0x7FFF0000
0x7FFFFFFF
0xBFFF0000
0xBFFFFFFF
0x000007FF FFFF0000
0x000007FF FFFFFFFF
0x000006FB FFFF0000
0x000000FB FFFFFFFF
内核模式分区 0x80000000
0xFFFFFFFF
0xc0000000
0xFFFFFFFF
0x00000800 00000000
0xFFFFFFFF FFFFFFFF
0x000006FC 00000000
0xFFFFFFFF FFFFFFFF

13.2 .1 空指针赋值分区

目的:引发违规。

在c++中,错误检查经常不够彻底,如下代码

int * pnSomeInteger  = (int * ) malloc(sizeof(int))
*pnSomeInteger = 5;

上面这段代码malloc如果没有足够内存,那么它会返回NULL,但是前面的代码汉有检查这一错误。注意:没有任何办法可以让我们分配到位于这一地址区间的虚拟地址空间。

13.2 .1 用户模式分区

这一分区是进程地址空间的驻地。可用的地址敬意和用户模式分区的大小取决于cpu体系结构

进程无法通过指针来读取,写入或以任何方式,访问驻留在这一分区中其它进程的数据。、

CPU体系结构,对应的用户模式可用地址区间以及大小

cpu体系结构 用户模式分区的可用地址区间 用户模式分区的大小
x86(普通) 0x00010000->0x7fffffff ~2GB
x86w/3GB 0x00010000->0xBFFFFFFF ~3GB
x64 0x000000000001000->0x000007FFFFFFFFFF ~8192GB
IA-64 0x00000000 00010000->0x000006FB FFFFFFFF ~7152GB

1. x86 Windows下得到更大的用户模式分区

2.在64位windows下得到2GB用户模式分区

3.内核模式分区

13.3 虚拟地址空间的分区

VirtualAlloc分配其中的区域(region)。分配区域的操作被称为预订(reserving)。

当预定时系统会确保区域的起始地址正好是分配粒度的整数倍。分配粒度会根据不同的CPU平台而有所不同。但是,在写作本书时所有CPu平台都使用相同的分配粒度,大小为64KB,也就是说,系统会把分配请求取到64KB的整数倍。

当应用程序预订地址空间中的一块区域时,系统会确保区域的大小为正好是系统页面大小的整数倍。页面是一个内存管理单元,系统通过页面来管理内存。与分配粒度相似页面大小与CPu不同而不同。x86和x64的页面大小为64KB,而IA-64系统使用的页面大小为8KB。

说明:

有时候系统会以应用程序的名义来预订地址空间区域。例如,系统会分配一块地址区间来存放进程环境块(PEB)。PEB是一个完全由系统创建,操控并销毁的小型数据结构。

系统同时还需要创建线程环境块(TEB),系统会在线程创建时分配TEB区域,并在销毁线程时释放相应区域。

13.4 给区域调拨物理存储器

为了使用所预订的地址空间区域,我们还必须分配物理存储器,并将存储器映射到所预订的区域。这个过程被称为调拨(committing)物理存储器。物理存储器始终都以页面为单位来调拨。我们通过调用VirtualAlloc来将物理存储器给所预订的区域。

当我们调拨物理存储器给区域时,并不需要给整个区域都调拨物理存储器。例如,我们可以预订一块大小为64KB的区域,然后把物理存储器拨给该区域中的第2个页面和第4个页面。

当程序不再需要访问所预订区域中已调拨的物理存储器时,应该释放物理存储器。这个过程被称为撤销调拨(decommitting)物理存储器,通过调用VirtualFree来完成。

13.5 物理存储器和页交换文件

页交换文件:硬盘上的文件一般被称为页交换文件,其中包含虚拟内存,可供任何程序使用。

不在页交换文件中维护物理存储器

在读过上一节之后,读者可能会想到,如果许多程序同时运行,页交换文件可能会变的相当大----尤其是每次运行一个程序时,系统都必须为该进程的代码和数据预订地址空间区域,为这些区域调拨物理存储器,然后把硬盘上程序文件中的代码和数据复制到页交换文件中已调拨的物理存储器中去。事实上,系统并不会执行刚才所说的这些操作。

如用户要求执行一个应用程序时,系统会打开该应用程序对应.exe文件并计算出应用程序的代码和数据的大小,。然后系统会预订一块地址空间,并注明与该区域相关靠人为生者物理存储器就是exe文件本身。是的,系统燕没有从页交换文件中分配空间,而是将exe文件的实际内容(或文件映象即file image)用作程序预订的地址空间区域。这样一来,不但载入程序非常快,而且页交换文件也可以保持一个合理的大小。

当把一个程序位于硬盘上的文件映象(即一个exe或 dll文件)用作地址空间区域对应的物理存储器时,我们称这个文件映象为内存映射文件(memory mapped file)。当载入一个exe或dll时,系统会自动预订空间区域并把文件映象映射到该区域。但是,系统也提供了一组函数,可以上开发人员把数据文件映射到地址空间。

说明:

当windows从软盘载入.exe或.dll文件时,系统会把整个文件从软盘复制到内存中,此外,系统还会从页交换文件中分配足够的存储空间来存放文件映象。只有当系统需要把一个页面换出内存,而页面又包含文件映象的一部份时,系统才会写入页交换文件。如果系统的内存负载很轻,那么文件总是在内存中运行。

Microsoft必须让软盘上执行的文件以这种方式 运行,因为只有这样安装程序才能正常运行。通常安装程序从第一张软盘开始,在安装过程中用户会取出该软盘并插入其它软盘。如果系统需要再从第一张软盘去加载exe或dll的一部分代码,那么很显然,第一张软盘可能已经不在软驱中了。但是由于系统已经把文件复制到了内存中(并以页交换文件为后备存储器),因此系统可以随时访问安装程序而且不会遇到任何问题。

除非映象文件是用/SWAPRUN:CD或/SWAPRUN:NET开关链接的,否则系统不会把位于其它可移动媒介(比如 光盘、或网络驱动器)上的映象文件复制到内存中的。

时间: 2024-07-30 01:44:14

《windows核心编程》–Windows内存体结构(一)的相关文章

018_《Delphi下深入Windows核心编程》

<Delphi下深入Windows核心编程> Delphi 教程 系列书籍 (018) <Delphi下深入Windows核心编程> 网友(邦)整理 EMail: shuaihj@163.com 下载地址: Part1 Part2 Part3     书名: Delphi下深入Windows核心编程 作者: 飞思科技产品研发中心 出版社: 电子工业出版社 书号: 7505384023 出版日期:2003年1月 开本: 787*1092 1/16 页码: 525 版次: 2003年1

《windows 核心编程》 -探索虚拟内存

14.1 系统信息 操作系统中有许多值 是由系统所运行的主机所决定的.如果页面大小和分配粒度等.我们决对不应该在代码中将这些值写死. 此函数得到系统信息VOID GetSystemInfo(LPSYSTEM_INFO ps) 如果想得到机器中与处理器有关的详细信息可以调用GetLogicalProcesorInfomation函数 为了让32位应用程序在64位版本的Windows运行,Microsoft提供了一个称为windows 32 bit On Windows 64 的模拟层又称为WOW.

《windows核心编程系列》二谈谈ANSI和Unicode字符集 .

http://blog.csdn.net/ithzhang/article/details/7916732转载请注明出处!! 第二章:字符和字符串处理     使用vc编程时项目-->属性-->常规栏下我们可以设置项目字符集合,它可以是ANSI(多字节)字符集,也可以是unicode字符集.一般情况下说Unicode都是指UTF-16.也就是说每个字符编码为两个字节.65535个字符可以表示世界上大部分的语言.为了软件使国际化大家再编程时应该使用unicode字符集.由于原来学过c语言,不习惯

[原创/讨论][windows核心编程一外传]关于访问虚拟地址0的方法。

接上一篇 Windows 核心编程研究系列之一(改变进程 PTE) 内容 上一篇观赏地址 :http://community.csdn.net/Expert/topic/5124/5124747.xml?temp=.2832453 当然系统保证不让访问地址0出于一种保护的目的,是防止未初始化的指针读取数据.我说的访问地址0只是出于一种纯实现的目的,也不提倡大家这样做.说白了只是好玩罢了. 大家都知道在 windows 中读取/写入地址0的指令肯定会出错: // 写 0 地址的内容xor edx,

请教windows核心编程 ErrorShow程序例子问题

问题描述 请教windows核心编程 ErrorShow程序例子问题 刚刚学习win32 有个问题TCHAR buffer[100]; case WM_PAINT:{ hdc = BeginPaint (hwnd &ps) ; DWORD systemLocale = MAKELANGID(LANG_NEUTRAL SUBLANG_NEUTRAL); DWORD dwError = 1; HLOCAL hlocal = NULL; BOOL fOk = FormatMessage( FORMAT

Windows 核心编程研究系列之一(-改变进程PTE属性-)[已补完]

  Windows 核心编程研究系列之一 -改 变 进 程 PTE 属性-              这是我研究windows 核心编程的第一篇正式文章,之所以叫核心编程而不叫内核编程,是我觉得从字面上来看核心(core)比内核(kernel)更靠近windows中心,当然只是偶本人的看法的拉.          我们知道在 win NT 中,系统把每个进程的虚拟4G空间分为两大部份,低2G归用户所有,高2G归系统所有.用户不得访问系统的空间,连读都不行,更别说写了!低2G的用户空间也并不是都能

chHANDLE_DLGMSG(windows核心编程)讲解

看完<Windows程序设计>后开始看<windows核心编程>, 结果看第一个案例的时候就很惊人的发现,Jeffery大牛的代码很深奥.乍一看好像没有包含<windows.h>. 看看包含的头文件发现,CmnHdr.h中已经包含了<windows.h>.而CmnHdr.h中的代码更吓人,如果没有讲解,不知道怎么看才好.后来才知道原来书的最后有专门的搭建环境的介绍,基本上全面的讲解了CmnHdr.h的东西.   CmnHdr.h中包含了大牛的很多自己的东西.

《windows核心编程》–Windows内存体结构(二)

13.6页面保护属性     内存页面保护属性有 PAGE_NOACCESS.PAGE_READONLY.PAGE_READWRITE.PAGE_EXECUTE.PAGE_EXECUTE_READ.PAGE_EXECUTE_READWRITE.PAGE_WRITECOPY.PAGE_EXECUTE_WRITECOPY.这些保护分别表示什么http://127.0.0.1:47873/help/1-3788/ms.help?method=page&id=09839DB7-2118-4A7D-A70

《windows核心编程》 17章 内存映射文件

内存映射文件主要用于以下三种情况: 系统使用内存映射文件载入并运行exe和dll,这大量节省了页交换文件的空间以及应用程序的启动时间 开发人员可以使用内存映射文件来访问磁盘上的数据文件.这使得我们可以避免直接对文件IO操作和对文件内存进行缓存 进程间通讯 17.1 映射到内存的可执行文件和DLL 当一个线程调用CreateProcess的时候,系统会执行收入步骤: 1.判断exe位置,如果无法找到exe那么不会创建进程,这时会CreateProcess返回FALSE 2.创建一个新的进程内核对象