(转)Windows 内存管理

摘要:
1.Windows的内存结构Windows系统中的每个进程都有自己的虚拟地址空间。每个进程的虚拟地址空间应划分为不同的分区。地址空间的划分基于操作系统的基本实现。不同的Windows内核有稍微不同的分区。

1Windows的内存结构

Windows系统中的每个进程都被赋予它自己的虚拟地址空间。对于32位进程来说,这个地址空间是4GB,因为32位指针可以拥有从0x000000000xFFFFFFFF之间的任何一个值。对于64位进程来说,则这个空间是16EB。由于每个进程可以接收它自己的私有的地址空间,因此当进程中的一个线程正在运行时, 该线程也只能访问只属于它的进程的内存。属于所有其他进程的内存则隐藏着,并且不能被访问。

每个进程的虚 拟地址空间都要划分成各个分区,地址空间的分区时根据操作系统的基本实现来进行的,不同的windows内核,其分区也略有不同。下面以32windows 2000 (x86alpha处理器)

分 区

地 址范围

作 用

NULL指针分配的区域

0x00000000

为了帮助掌握NULL指针的分配情况,任何读写都将引发访问违规

0x0000FFFF

用户方式分区

0x00010000

这是进程的私 有空间,该分区是维护进程的大部分数据的地方。

0x7FFEFFFF

64k 禁止进入分区

0x7FFF0000

这个分区是禁 止进入的,任何访问都将是违规。保留此分区是为了更加容易地实现操作系统。怕用户内存越界到内核区。

0x7FFFFFFF

内核方式

0x80000000

这个分区是存 放操作系统代码的地方。用于线程调度、内存管理、文件系统支持等以及设备驱动程序的代码全部在这个分区加载。

0xFFFFFFFF

 

另外,如果用 户想把用户方式分区扩大到3GB,则在x86windows 2000 advanced server版本和windows 2000 data center版本中可以加入/3GB开关到BOOT.INI文件中。使用/3GB开关后,将减少系统能够创建的线程、堆栈和其他资源的数量。此外,系统最多使用16GBRAM,而通常情况下可以使用64GBRAM。因为内核方式中没有足够的虚拟空间来管理更多的RAM

2.地址空间中的区域

当进程被创建 并被赋予它的地址空间时,该可用空间的主体是空闲的,未分配的。若要使用该地址空间的各个部分,必须要调用virtualAlloc 函数来分配它里边的各个区域。对每一个地址空间的区域进行 分配的操作称为保留(reserve

   当你保留地址空间的一个区域时,该区域必须是系统的页面大小的倍数,而且分配边界必须从一个分配粒度开始。例如x86的页面大小为4KB,分配粒度为64KB

 若要使用已保留的地址空间区域,则必须分配物理存储器,然后将该物理存储器映射到已保 留的地址空间区域。这个过程叫提交物理存储器。也调用VirtualAlloc函数,但和前面保留的输入参数有所区别,可以自己查此函数。当然用户也可以在保留地址空 间的同时提交物理存储器。

 在较老的操作系统中,物理存储器被视为计算机所有的RAM的容量。如果计算机有16MRAM,则加载和运行的应用程序最多可以使用16MRAM。今天的操作系统则使得磁盘空间看上去像内存一样。磁盘上的文件通常称为页文件,它包含 了可以供所有进程使用的虚拟内存。(用户可以在“我的电脑->属性->高级”里面查看虚拟内存的页文件信息)

这样,当一个 应用程序通过调用VirtrualAlloc函数,将物理存储器提交给地址空间的一个区域时,地址空间实际上是从硬盘上的一个文件中 进行分配的。

 当用户进程中的一个线程试图访问进程的地址空间中的一个数据块的时候。一般会发生两种 情况:

1. 线程试图访问的数据是在RAM中,则cpu只需要将虚拟地址映射到内存的物理地址中,然后执行需要的访问。

2. 数据不在RAM中,而是放在页文件的某个地方。这时候,访问引起页面失效,cpu将通知操作系统,操作系统就从RAM中寻找一个空白页,如果找不到空白页,则必须释放一个页。如果该页面没有被修改过,则 可以直接释放,否则必须先把此页面从RAM拷贝到页面交换文件,然后系统进入该页文件,找出需要访问的数据,并将数据加载到空闲的内存页面。然后,操作系统更新它的用于指明数据的虚拟内存地址现在已经映射到RAM中的相应的物理存储器地址中的表。

3. Windows的内存管理方法

 windows提供了3种方法来进行内存管理:

l         虚拟内存,最适合用来管理大型对象或者结构数组

l         内存映射文件,最适合用来管理大型数据流(通常来自文件)以及在单个计算机上运行多个进程之间共享数据。

l         内存堆栈,最适合用来管理大量的小对象。

31 虚拟内存

 虚拟内存的使用主要有以下几个步骤:

1. 在地址空间保留一个区域,调用函数VirtualAlloc

2. 在保留区域中的提交物理存储器,当保留一个区域后,必须将物理存储器提交给该区域,然 后才能访问该区域中包含的内存地址。系统从它的页文件中将已提交的物理存储器分配给一个区域。仍旧调用函数VirtualAlloc具体参数设置可以见msdn,当然,用户也可以一次性地进行操作保留区域和提交物理存储器。

3. 回收虚拟内存和释放地址空间区域,调用VirtualFree函数,并且,如果要释放一个区域,必须释放该区域保留地所有地址空间。当然用户也可以只回收物理存储器而不释放区域,仍旧调用VirtualFree函数,但参数传入不同。

32 内存映射文件

 与虚拟内存一样,内存映射文件可以用来保留一个地址空间的区域,并将物理存储器提交给该 区域。他们之间的区别是,物理存储器来自一个已经位于磁盘上的文件,而不是系统的页文件。一旦该文件被映射,就可以访问它,就像整个文件被加载到了内存一 样。

   内存映射文件 一般用于3个不同 的目的:

1.       系统使用内存映射文件,以便加载和执行.exeDLL文件。这可以大大节省页文件空间和应用程序启动运行所需的时间

2.       可以使用内存映射文件来访问磁盘上的数据文家爱女。这使你可以不比对文件执行i/o操作,并且可以不必对文件内容进行缓存

3.       可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据。

若要使用内存映射文件,必须执行下列操作步骤:

1创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件 (CreateFile函数)

2创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件

CreateFileMapping函数)

3让系统将文件映射对象的全部或一部分映射到你的地址空间

MapViewOfFile函数,要求文件的位移是分配粒度的倍数)

当完成对内存映射文件的使用时,必须执行下面的这些步骤将它清除:

4)告诉系统从你的进程的地址空间中撤销文件映射内核对象的映象

(UnmapViewOfFile函数)

5)关闭文件映射内核对象

CloseHandle函数,第2)步创建的对象)

6)关闭文件内核对象

(CloseHandle函数,第1)步创建的对象)

利用内存映射文件,还可以实现进程之间的数据共享。数据共享的方法是通过让两个或多个进程映射同一个文件映射对象的视图,这也意味着他们将共享物理存储器的同一个页面。另外,用户也可以创建由系统的页文件支持的内存映射文件,而不是由专用硬盘文件支持的内存映射文件。这样,就不需要调用CreateFile函数,只需要给CreateFileMappingHfile参数传递INVALID_HANDLE_VALUE,并传递一个以0结尾的字符串作为pszName参数。别的进程就可以用CreateFileMapping或者OpenFilemapping函数。

 33 堆栈

 堆栈可以用来分配许多较小的数据块,例如对链接表和链接树进行管理等。堆栈的优点是, 可以不考虑分配粒度和页面边界之类的问题。堆栈的缺点是,分配和释放内存块的速度比其他机制要慢,并且无法直接控制物理存储器的提交和回收。

   当进程初始化时,系统在进程的地址空间中创建一个堆栈。该堆栈为进程的默认堆栈。按照默认设置,该堆栈的地址空间区域的大小是1MB。系统可以扩大进程的默认堆栈。由于进程的默认堆栈可以供许多windows函数调用,因此对默认堆栈的访问是按顺序进行的。也就是,系统必须保证在规定的时间内,每次只有一个线程能分配和释放默认堆栈中的内存块。 当然,用户也可以在进程的地址空间中创建一些辅助堆栈。

 堆栈的一些操作函数如下(具体可以查msdn):

1.创建堆栈    HeapCreate

2. 从堆栈中分配内存块 HeapAlloc

3. 改变内存块的大小 HeapReAlloc

4. 释放内存块 HeapFree

5. 撤销堆栈   HeapDestroy

免责声明:文章转载自《(转)Windows 内存管理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇c#原理:c#代码是怎么运行的、实例化时发生了什么、静态对象(类、方法、变量、属性)的原理我的华为面试经历——技术服务下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

QNX 实时操作系统(Quick Unix)

Gordon Bell和Dan Dodge在1980年成立了Quantum Software Systems公司,他们根据大学时代的一些设想写出了一个能在IBM PC上运行的名叫QUNIX(Quick UNIX)的系统,直到AT&T发律师函过来才把名字改成QNX。 中文名 QNX 实时操作系统 POSⅨ 规范 系统 嵌入式系统 目录...

打印堆栈信息

#ifdef OS_IBM sprintf(szCmd,"%s %d >>%s", "procstack", getpid(),abnTraceFileName); system(szCmd);#else sprintf(szCmd,"%s %d >>%s", "pstack", getpid(),abnTraceFileName)...

二、NOSQL之Memcached缓存服务实战精讲第一部

1.Memcached是一套数据缓存系统或软件。 用于在动态应用系统中缓存数据库的数据,减少数据库的访问压力,达到提升网站系统性能的目的;Memcached在企业应用场景中一般是用来作为数据库的cache服务使用;(但不是专门干这个,还可以干别的,主要是干这个,知道就好) 1)linux有特性,系统内存没有用完,利用这些内存就会缓存起来,所以剩余的内存为...

mySQL内存及虚拟内存优化设置

为了装mysql环境测试,装上后发现启动后mysql占用了很大的虚拟内存,达8百多兆。网上搜索了一下,得到高人指点my.ini。再也没见再详细的了..只好打开my.ini逐行的啃,虽然英文差了点,不过多少M还是看得明的^-^ 更改后如下: innodb_buffer_pool_size=576M ->256M InnoDB引擎缓冲区占了大头,首要...

CAM(内容可寻址存储器)的认知

     内容可寻址存储器CAM(Coment-Addressable Memo-ry)以内容进行寻址的存储器,是一种特殊的存储阵列RAM。它的主要工作机制就是将一个输入数据项与存储在CAM中的所有数据项自动同时进行比较,判别该输入数据项与CAM中存储的数据项是否相匹配,并输出该数据项对应的匹配信息。 内容可寻址存储器的特性         1、160 n...

Windows系统中CreateFileMapping实现的共享内存及用法

在32位的Windows系统中,每一个进程都有权访问他自己的4GB(232=4294967296)平面地址空间,没有段,没有选择符,没有near和far指针,没有near和far函数调用,也没有内存模式。 每个进程都有独立的4GB逻辑地址空间,32位的Windows系统允许每一个进程独立访问自己的内存,即独立于其它进程,也即它自己的32位逻辑地址空间。操作...