现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

对Windows内存的理解和总结摘录

2012-12-13 12:19 工业·编程 ⁄ 共 2346字 ⁄ 字号 暂无评论

说明: 由于是非计算机专业的学生,所以一直对Windows内存没什么特别的认识。由于一个项目用到使用内存映射文件来进行大文件处理,对其原理不是很明白,于是翻看了这块知识点,进行了一次恶补,主要看了《精通Windows API》、《Windows核心编程》、内存映射文件的使用(http://www.51testing.com/?uid-2243-action-viewspace-itemid-202461)。以下是我根据自己的理解思路,从资料中摘录出来的一些知识点,主要用于自己以后翻看。

 

1、 虚拟地址空间

每个进程都有自己的虚拟地址空间。对于32位进程来说,这个地址空间的大小为4GB(0x0000,0000—0xFFFF,FFFF)。

每个进程的虚拟地址空间被划分成几个分区,如下图所示。

 

2、 虚拟地址到物理地址的映射

①根据CR3寄存器中值的第12-32位,找到页目录所在的物理页地址;

②根据虚拟地址第22-32位,找到相应的页目录项,页目录项中有这个虚拟地址所对应的页表的物理地址;

③根据虚拟地址第12-21位,找到该页表中相应的页表项,页表项中有这个虚拟地址所对应的物理页的地址;

④用虚拟地址的低12位,即页内偏移,加上物理页的地址,即得到了该虚拟地址对应的物理地址。

注:

对于32位windows,页面的大小是4KB。

页表,一个页表的大小是4KB,放在一个物理页中,由1024个4KB的页表项组成,页表项中存放一个物理页的物理地址;

页目录,一个页目录的大小为4KB,放在一个物理页中,由1024个4KB的页目录项组成,页目录项中存放一个页表的物理地址;

在X86平台上,CR3寄存器存放了页目录所在的物理地址。系统运行时,CR3寄存器中保存的页目录地址是会变化的,其值为当前运行的进程的页目录地址。

 

3、 地址空间中的区域

当系统创建一个进程并赋予它地址空间时,可用地址空间中的大部分都是闲置的或尚未分配的。为了使用这部分地址空间,我们必须调用VirtualAlloc来分配其中的区域。分配区域的操作被称为预订

当应用程序预订地址空间中的一块区域时,系统会确保区域的起始地址正好是分配粒度的整数倍。分配粒度会根据不同的CPU平台而不同,一般为64KB。

当应用程序预订地址空间中的一块区域时,系统会确保区域的大小正好是系统页面大小的整数倍。

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

当程序不再需要访问所预订的地址空间区域时,应该释放该区域。这个过程被称为释放地址空间区域,通过调用VirtualFree函数来实现。

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

例:

如果我们想在进程地址空间中其实地址为19668992(300*65536+8192)的地方预订区域,那么系统会把该地址向下取整到64KB的整数倍,即19660800(300*65536),然后在取整后的地址预订区域。

如果预订62KB大小的区域的话,那么最终得到的区域大小会是64KB。

 

4、 页交换文件

当今的操作系统能让磁盘空间看起来像内存一样。磁盘上的文件称为页交换文件磁盘上的虚拟内存),页交换文件可增大应用程序可用的内存总量。

当一个线程试图访问所属进程的地址空间的一块数据时,有可能会出现两种情况,如下图流程所示(把虚拟地址转换为物理地址)。

系统需要在内存页交换文件之间复制页面的频率越高,硬盘颠簸的越厉害,系统运行的也越慢。

5、 内存映射文件

除了上述的页交换文件外,硬盘上的内存还可以通过内存映射文件的方式来分配。它的物理存储器来自磁盘上已有的文件,而不是系统的页交换文件

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

 

6、 利用内存映射文件来访问磁盘上的数据文件

①个人理解:

使用内存映射文件来访问磁盘上的数据文件,可以避免直接对文件进行I/O操作和对文件内容进行缓存。

比如,利用CreateFile等函数对文件进行对写入时,我们首先定义一个变量,分配一块内存,用于存放数据,然后再通过I/O操作写入文件;而利用内存映射文件时,程序的虚拟地址空间的某个区域已与磁盘的物理地址建立了映射关系,可以直接对文件数据进行操作。

②使用内存映射文件的步骤:

调用CreateFile目的是告诉操作系统文件映射的物理存储器所在的位置;

调用CreateFileMaping目的是告诉系统文件映射对象需要多大的物理存储器,确保足够的物理存储器可供文件映射对象使用。

在创建了文件映射对象后,还需要调用MapViewOfFile为文件的数据预订一块虚拟地址空间并将文件的数据作为物理存储器调拨给区域。

注:

①Windows允许我们以同一个数据文件为后备存储器来创建多个文件映射对象。Windows并不保证这些不同的文件映射对象的各个视图是一致的。系统只保证在同一文件映射对象的多个视图间保持一致

②当我们把一个文件映射到进程的地址空间中时,不必一下子映射整个文件,可以每次只把文件的一小部分映射到地址空间中。把文件的一个视图映射到进程的地址空间时,需要告诉系统两件事情:第一,必须告诉系统应该把数据文件中的哪个字节映射到视图中的第一个字节;第二,必须告诉系统要把数据文件中的多少映射到地址空间中去。

给我留言

留言无头像?