window内存管理与内存原理
转自: http://blog.csdn.net/iamfranter/article/details/6826270
当我们在Windows中双击一个应用程序图标后,系统为该应用程序创建一个进程,Windows使得每个进程都拥有2GB的地址空间,这2GB地址空间用于程序存放代码,数据,堆栈,自由存储区(堆),另外2GB用于共享系统使用
前面的这些地址并不是物理内存中的地址,而是该进程空间中的虚拟地址,虚拟空间只是Windows为该进程分配的一个虚拟的地址空间,只有当其和物理内存相关联后才有意义
内存的分页
每个物理地址对应一个虚拟地址?1GB那页表该有多长,所以将内存分页管理,4K为一页,即4K就是一个最小单位。虚拟地址到物理地址的映射见图,中间的那个就是页表了。
如何映射?
进程被创建时会建立一个 虚拟内从到物理内存的映射表--------页表,根据页表可以将虚拟内存和物理内存关联起来
-----------------------------------------页表如何工作,怎么将虚拟地址关联物理地址----------------------------------
虚拟内存是什么?
就是把磁盘拿来当内存用,这是以前买电脑时的想法。
所以就一直都想不明白一个问题:要真是这样,那内存分个什么1GB,2GB,4GB,大家都买个1M的内存条,然后把自己磁盘拿来当内存用多好,比2GB,4GB不知道要大多少。
其实这个说法有一点擦边球的味道,虚拟内存是一些系统页文件,存放在磁盘上,每个系统页文件大小也为4K,物理内存也被分页,每个页大小也为4K,这样虚拟页文件和物理内存页就可以对应,实际上虚拟内存就是用于物理内存的临时存放的磁盘空间。
页文件就是内存页,物理内存中每页叫物理页,磁盘上的页文件叫虚拟页,物理页+虚拟页就是系统所以使用的页文件的总和。还有映像页文件和映射页文件,映像页文件就是拿程序本身当页文件使用(而不是用系统的页文件),映射页文件就是使用磁盘上的文件(非系统页文件)来当页文件使用(这主要用于读取文件)。
虚拟地址页的状态:
空闲:该区域没有被所使用,也没有被预定,没有和物理内存管理
私有:该区域虽然没有被使用,但是已经被申请(预定了),别人无法使用它。同样也没和物理内存关联
提交:该区域已经和物理内存管理,可以使用了
虚拟内存和物理内存的管理(Windows内存管理的核心)
Windows是多任务的系统,在每个进程创建时,系统为每个进程也创建了一个页表,用于虚拟地址到物理地址的转换。比如现在程序在执行进程A,用户切换到了另外一个进程B,则系统会将进程A在内存中的数据存放到页文件中,并更新进程A的页表(使虚拟地址和页文件形成映射)。然后读取进程B的页表,根据页表判断进程B的数据是在内存中还是在页文件中(通过页文件的类型来判断),如果在内存中就直接读取,如果在页面文件中,就将页面文件内容读入物理内存,然后更新页表(使虚拟地址和物理内存形成映射)。这样一看,虚拟内存实际上就是冒牌的物理内存了吧。
程序的执行
一个PE文件有数据区,代码区,堆栈区(由系统分配,用于管理局部变量),使用OD载入一个程序就可以知道这些都是以二进制的形式保存在文件中。
程序刚运行的时候,系统不直接将整个程序载入到物理内存中,也不将其载入到页文件中,而是以程序文件本身作为页文件形成映射(虚拟地址到页文件的映射),建立页表,然后随着程序的执行通过页表来将其虚拟地址转换成物理地址(将页文件读入内存),然后在读取内存中的指令或数据。当进程被切换时,将内存内容保存到页文件,更新页表,如此往复,实现多任务操作。
可以知道,程序的代码段,数据段,堆栈区(系统分配)这些虚拟地址区域已经是映射状态,即有相应的物理内存与之对应。系统为每个进程提供了2G的自己的虚拟地址空间,剩下的虚拟地址空间干什么用?
剩下的虚拟地址空间就是给程序运行时动态分配内存使用。C++中 new的功能就是动态分配地址空间:
申请内存的最小单位是区域,每个区域为CPU粒度大小,即64K,每次申请的内存都必须是64K的整数倍,C++ new功能申请一个区域,保留该区域,然后提交需要的页,其他的保留。
char *address=new char[1024]; //分配1K的内存
这条语句首先申请一个区域的地址空间,表示这个区域已经被预定了,这就是上述区域状态中的私有状态,虽然预定了,但是还没有和物理内存关联起来,所以程序也无法使用该内存,然后程序将这1K的内存提交,就是映射到了内存当中,区域的状态就变成了映射状态,这样程序就可以使用这1K的内存了,而剩下的页仍然为保留状态。那当进程被切换时,这1K的进程存放在哪呢?程序本身的页文件已经被 代码,全局数据,堆栈这些所使用了,所以系统会为自由存储区分配的内存分配新的页文件来做虚拟内存。
局部变量的定义是由系统分配的,它将局部变量分配到堆栈区,因为堆栈区已经映射了,所以不用在映射,故不用使用新的页文件了。堆栈区的大小为1M左右,如果分配的局部变量超过1M会产生堆栈溢出。
可以看到,系统的单个页文件大小为4K,程序自己的虚拟空间地址从00010000到7FFEFFFF差不多是2G
动态分配一个500M的内存后,物理内存,页文件,可用的虚拟地址空间都减少了500M
查询内存状态使用VirtualQuery(Address[n],&membaseinf,sizeof(MEMORY_BASIC_INFORMATION))
定义3个变量
char Stack[20*1024]; //存在堆栈中,堆栈在程序启动时已经被映像到内存中了
char* Dynamic=new char[64*1024]; //动态分配一个70K的内存
char* Dynamic2=new char[1024]; //动态分配一个1K的内存
地址所在页面基地址:查询的地址所在的页面的起始地址
页面所在区域的基地址:页面所在区域的起始地址
区域保护属性:分配区域时要设置区域的读写属性
从页面基地址开始拥有相同属性(空闲,保留,提交)的所有页的字节数:可以看到这些都是4096的整数倍,因为一个页4096,该大小一般都和申请的内存空间大小相当,因为这些内存都被提交了。
申请一个内存空间的过程
首先申请一个虚拟地址空间区域,然后提交申请的内存空间大小的页(将其和页文件关联)。其他的地址空间保留。
第一条指令分配了一个字符数组的局部变量,该变量分配在堆栈中,由系统分配,所以其区域为程序的静态存储区,即在程序启动时候这个区域的所有虚拟地址就和程序文件本身映像了,所以局部变量的区域基地址都是一样的,那为什么它的页面文件类型是页文件呢?不应该是exe映像么?因为现在文件在内存中,所有是物理页,就是页文件。
第二条指令动态分配了一块大小为1K的内存区域,这块内存分配在自由存储区,它所在的区域是在堆中申请的一个区域,第三条指令在堆中分配了一个70K左右的内存,因为他们是在堆中分配的,所以这2个变量的区域基地址是不一样的。
分配的区域有多大?
第三条指令分配了一个70K左右的内存,它会向系统申请多大的区域呢?由区域大小为64K的整数倍知该区域至少为128K,查询这70K之后的虚拟地址的状态
可以看到该地址所在的区域和Dynamic是一样的,它的基地址为594000,在那70K之后,这之后的区域的状态为保留,说明系统保留了剩下的区域,这剩下的区域有966656,就是966K左右的大小,那整个区域的大小就是(0x14000)81920+966656。
- 上一篇:指针与内存
window内存管理与内存原理的更多相关文章
- SAP专家培训之Netweaver ABAP内存管理和内存调优最佳实践
培训者:SAP成都研究院开发人员Jerry Wang 1. Understanding Memory Objects in ABAP Note1: DATA itab WITH HEADER LINE ...
- iPhone/Mac Objective-C内存管理教程和原理剖析
http://www.cocoachina.com/bbs/read.php?tid-15963.html 版权声明 此文版权归作者Vince Yuan (vince.yuan#gmail.com)所 ...
- Objective-C内存管理教程和原理剖析(四)
初学Objective-C的朋友都有一个困惑,总觉得对Objective-C的内存管理机制琢磨不透,程 序经常内存泄漏或莫名其妙的崩溃.我在这里总结了自己对Objective-C内存管理机制的研究成果 ...
- Objective-C内存管理教程和原理剖析(三)
初学Objective-C的朋友都有一个困惑,总觉得对Objective-C的内存管理机制琢磨不透,程 序经常内存泄漏或莫名其妙的崩溃.我在这里总结了自己对Objective-C内存管理机制的研究成果 ...
- 内存管理cpuset,mempolicy[原理]
介绍cpuset,mbind,set_mempolicy在内存管理上的应用 change log :确定先从mempolicy的man 手册翻译开始研究,计划如下 .先从man手册入手,通过实现mem ...
- Delphi的内存管理及内存泄露问题 FastMM4
这几天因为一个程序长时间运行出现比较严重的内存泄露问题,开始关注了一下内存管理方面的东西,以前也注意内存管理,创建了对象及时释放,但总有忘了处理的情况. 在Delphi中没有自动回收机制,所以一定要及 ...
- Android 之 内存管理-查看内存泄露(三)
概述 在android的开发中,要时刻主要内存的分配和垃圾回收,因为系统为每一个dalvik虚拟机分配的内存是有限的,在google的G1中,分配的最大堆大小只有16M,后来的机器一般都为24M,实在 ...
- 启动期间的内存管理之bootmem_init初始化内存管理–Linux内存管理(十二)
1. 启动过程中的内存初始化 首先我们来看看start_kernel是如何初始化系统的, start_kerne定义在init/main.c?v=4.7, line 479 其代码很复杂, 我们只截取 ...
- Linux内存管理 (22)内存检测技术(slub_debug/kmemleak/kasan)
专题:Linux内存管理专题 关键词:slub_debug.kmemleak.kasan.oob.Redzone.Padding. Linux常见的内存访问错误有: 越界访问(out of bound ...
随机推荐
- 鲁棒性是 Robustness
鲁棒性是 Robustness 的音译,是指当系统受到不正常干扰时,是否还能保证主体功能正常运作.可参考 维基百科:http://zh.wikipedia.org/zh/ 鲁棒性 _( 计算机科学 ) ...
- php判断来源网址地址并且限制非法来源
$fromHost = array( 'paipai.com', 'localhost', '127.0.0.1' ); $s = 'http://www.paipai.Com/chong/abc.s ...
- 关于使用regsvr32命令注册ActiveX控件失败的解决办法
昨天小编也遇到这样问题,步骤一切都对,没有错误,但是每次在命令行下输入的时候,都会弹出一个对话框: 最后我发现是存放ActiveX控件的路径中带有中文文件名字所导致,所以导致的错误,我们将所在路径下的 ...
- asdoc 档案
1.asdoc air项目会出现无法找到NativeApplication等错误 解决办法:add args -load-config ....../frameworks/air-config.x ...
- windows和linux环境下制作U盘启动盘
新笔记本上,要装xp的系统,100%会破坏原有的Linux系统,因为安装xp的时候会自动覆盖硬盘的主引导扇区,这个扇区一旦被重写,那么原有的linux根本就启动不了. 要想玩linux和xp双系统,一 ...
- js基础知识点(只有点)
转自:2015年12月的文章 http://blog.csdn.net/u014326381/article/details/50176339 JavaScript: 作用域链.闭包.运行时上下文.t ...
- 解决jquery-easyui1.3.3 combobox 多选模式不兼容IE8问题
扩展Array的原型对象,加入indexOf方法 if(!Array.prototype.indexOf){ Array.prototype.indexOf = function(target) ...
- ffmpeg 发布hls流
本来主要讲述如何利用ffmpeg将输入视频流通过转码的方式转成m3u8文件.如何通过http的方法将切边推送给客户端,不在本文中讲述. 输入视频流可以是rtsp流,也可以是http,还可以是文件等等. ...
- Upgrading to Java 8——第三章 Optional and Similar Classes
Java程序员对付空指针异常已经好多年了.在Java8中将有新的方式去处理他们.通过包装一个潜在的可能为null的类称为Optianal. 在Java8中添加了the Optional, Option ...
- cf 496B Secret Combination
题目链接:B. Secret Combination You got a box with a combination lock. The lock has a display showing n d ...