Windows API 之 VirtualAlloc(未完)

Reserves, commits, or changes the state of a region of pages in the virtual address space of the calling process. Memory allocated by this function is automatically initialized to zero.

LPVOID WINAPI VirtualAlloc(
  _In_opt_ LPVOID lpAddress,
  _In_     SIZE_T dwSize,
  _In_     DWORD  flAllocationType,
  _In_     DWORD  flProtect
);

为了更好的理解VirtualAlloc,我们需要先了解下虚拟内存技术原理。

Windows的内存结构是深入理解Windows操作系统如 何运作的最关键之所在,通过对内存结构的认识可清楚地了解诸如进程间数据的共享、对内存进行有效的管理等问题,从而能够在程序设计时使程序以更加有效的方 式运行。Windows操作系统对内存的管理可采取多种不同的方式,其中虚拟内存的管理方式可用来管理大型的对象和结构数组。

在Windows系统中,任何一个进程都被赋予其自己的虚拟地址空间,该虚拟地址空间覆盖了一个相当大的范围,对于32位进程,其地址空间为 2^32=4,294,967,296 Byte,这使得一个指针可以使用从0x00000000到0xFFFFFFFF的4GB范围之内的任何一个值。虽然每一个32位进程可使用4GB的地址 空间,但并不意味着每一个进程实际拥有4GB的物理地址空间,该地址空间仅仅是一个虚拟地址空间,此虚拟地址空间只是内存地址的一个范围。进程实际可以得到的物理内存要远小于其虚拟地址空间。进程的虚拟地址空间是为每个进程所私有的,在进程内运行的线程对内存空间的访问都被限制在调用进程之 内,而不能访问属于其他进程的内存空间。这样,在不同的进程中可以使用相同地址的指针来指向属于各自调用进程的内容而不会由此引起混乱。

在进程创建之初并被赋予地址空间时,其虚拟地址空间尚未分配,处于空闲状态。这时地址空间内的内存是不能使用的,必须首先通过VirtualAlloc()函数来分配其内的各个区域,对其进行保留

其参数lpAddress包含一个内存地址,用于定义待分配区域的首地址。通常可将此参数设置为NULL,由系统通过搜索地址空间来决定满足条件的未保留 地址空间。这时系统可从地址空间的任意位置处开始保留一个区域,而且还可以通过向参数flAllocationType设置MEM_TOP_DOWN标志 来指明在尽可能高的地址上分配内存。如果不希望由系统自动完成对内存区域的分配而为lpAddress设定了内存地址(必须确保其始终位于进程的用户模式分区中,否则将会导致分配的失败), 那么系统将在进行分配之前首先检查在该内存地址上是否存在足够大的未保留空间,如果存在一个足够大的空闲区域,那么系统将会保留此区域并返回此保留区域的 虚拟地址,否则将导致分配的失败而返回NULL。这里需要特别指出的是,在指定lpAddress的内存地址时,必须确保是从一个分配粒度的边界处开始。

内存的“保留”与“提交”:

Win32为系统中的每一个应用程序(进程)提供一个独立的、2   GB的用户地址空间。对于应用程序来说,好象是有2   GB的可用内存(实际上在Windows95/98,NT,Win2000   Advanced   Server/Enterprise   Server   上的内存分配略有不同),而不用考虑实际可用的物理内存的量。如果某个应用程序要求的内存比可用的内存更多时,Win32是这样满足这种要求的,它从这个 和/或其他的进程把非关键内存分页(paging)到一个页文件,并且释放这些物理内存页

在任意给定的时间,进程中每个地址都可以被当作是自由的、保留的或已提交的进程开始时,所有地址的都是自由的,意味着它们都是自由空间并且可以被提交到 内存,或者为将来使用而保留起来,但是它们不能存取(read/write)。在任何自由的地址能够被使用前,它必须首先被分配为保留的或已提交的

当在一个进程中保留地址时,没有物理内存页被提交,并且,也许更为重要的是,在页文件中没有为备份该内存而保留空间。而且,保留一个地址范围将不会保证将来会有可用的物理内存来提交给这些地址。实际上,它只是保存了一个指定的自由地址地址,一直到需要使用它时,而阻止了其它分配对该段地址的请求如果没有 这种类型的保护,那么例程操作(routine   operations),例如加载一个DLL或者资源,可能会占有指定的地址,并且危害以后对它的使用。  要使用保留的地址,内存首先必须被提交给该地址。提交内存到地址与保留内存相类似.调用VirtualAlloc,并且在调用时设置 dwAllocation参数等于MEM_COMMIT。在这一时刻,资源被提交到地址上。每一次,内存可以按一页的大小被提交。能够被提交的最大内存值 仅仅取决于连续的自由或者保留地址的最大范围(但两者不可组合在一起),无须考虑系统的可用物理内存的大小。

当内存被提交时,内存物理页被分配,并且该段空间被保留在在一个页文件中。也就是说,已提交的内存页总是以物理内存页或者在已经被分页的磁盘上的页文件的 形式存在。当提交一个大块内存时,在初始阶段,其部分或者全部内存没有驻留在物理内存中也是有可能的。某些内存页一开始驻留在页文件中,直到它被访问。在 系统中,一旦内存页已提交,虚拟内存管理器象对待所有其它的内存页一样对待它们。  
 
在Win32虚拟内存系统中,使用了页表(page  
tables)来访问物理内存页。每个页表本身也是一个内存页,象已提交的页一样。偶而,当提交内存时,同时还必须对页表分配附加的页。所以,提交一页内
存的请求可能需要为页表分配一页,为请求的页分配一页,并且在页文件中需要两页空间来备份这些页中的每一页。因此,VirtualAlloc完成一个内存
提交请求所需要的时间变化很大,它取决于系统的状态以及请求的空间大小。

“内存 - 提交大小:为某进程使用而保留的虚拟内存的数量。
对于已提交的页面,系统会根据总的内存使用情况来调度它们。当物理内存紧张时,系统会选择一些页面,将它们换出到内存文件中,待下次使用的时候,再将它们
换回来。通常情况下,应用程序并不需要干预系统的页面调度机制。在一些特殊情况下,应用程序也可以通过VirtualLock函数来锁住已提交页面,使得
它们总是留在物理内存中;以后再调用VirtualUnlock函数来结束这种锁定。”

关键字:

内存保留 内存提交

参考:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366887%28v=vs.85%29.aspx

http://www.yesky.com/67/1753067.shtml

http://super-man-woman.blog.163.com/blog/static/3789803820098532317144/

时间: 2024-10-10 23:26:53

Windows API 之 VirtualAlloc(未完)的相关文章

Windows线程同步(未完)

先介绍一个创建线程的API,参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx Creates a thread to execute within the virtual address space of the calling process. HANDLE WINAPI CreateThread( _In_opt_ LPSECURITY_ATTRIBUTES lpThr

Windows API Hook

原文地址:http://blog.sina.com.cn/s/blog_628821950100xmuc.html 原文对我的帮助极大,正是因为看了原文,我才学会了HOOK,鉴于原文的排版不是很好, 又没有原工程例子源码下载,因此我决定对其重新整理,文章后面附有我测试时的工程源码下载地址. 注:我测试的环境为Win7+VS2008+MFC 原文出处,好像是这篇:http://blog.csdn.net/glliuxueke/article/details/2702608      //后来才看到

whatweb.rb 未完待续

#!/usr/bin/env ruby #表示ruby的执行环境 =begin # ruby中用=begin来表示注释的开始 .$$$ $. .$$$ $. $$$$ $$. .$$$ $$$ .$$$$$$. .$$$$$$$$$$. $$$$ $$. .$$$$$$$. .$$$$$$. $ $$ $$$ $ $$ $$$ $ $$$$$$. $$$$$ $$$$$$ $ $$ $$$ $ $$ $$ $ $$$$$$. $ `$ $$$ $ `$ $$$ $ `$ $$$ $$' $ `$

Windows API 编程学习记录<三>

恩,开始写API编程的第三节,其实马上要考试了,但是不把这节写完,心里总感觉不舒服啊.写完赶紧去复习啊       在前两节中,我们介绍了Windows API 编程的一些基本概念和一个最基本API函数 MessageBox的使用,在这节中,我们就来正式编写一个Windows的窗口程序. 在具体编写代码之前,我们必须先要了解一下API 编写窗口程序具体的三个基本步骤:             1. 注册窗口类:             2.创建窗口:             3.显示窗口: 恩,

Delphi Windows API判断文件共享锁定状态

一.概述 锁是操作系统为实现数据共享而提供的一种安全机制,它使得不同的应用程序,不同的计算机之间可以安全有效地共享和交换数据.要保证安全有效地操作共享数据,必须在相应的操作前判断锁的类型,然后才能确定数据是否可读或可写,从而为开发出健壮的程序提供切实依据.   同样,在Windows中,文件可以共享模式打开,它也涉及到锁的操作问题.根据Windows中文件共享时加锁范围的大小,锁可分为全局锁和局部锁:全局锁以锁定文件全部内容为特征,而局部锁以锁定文件的局部内容为特征,且文件的锁定区域不可重复.根

Windows API 大全

常用Windows API1. API之网络函数WNetAddConnection 创建同一个网络资源的永久性连接WNetAddConnection2 创建同一个网络资源的连接WNetAddConnection3 创建同一个网络资源的连接WNetCancelConnection 结束一个网络连接WNetCancelConnection2 结束一个网络连接WNetCloseEnum 结束一次枚举操作WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接WNetDis

c运行库、c标准库、windows API的区别和联系

C运行时库函数C运行时库函数是指C语言本身支持的一些基本函数,通常是汇编直接实现的.  API函数API函数是操作系统为方便用户设计应用程序而提供的实现特定功能的函数,API函数也是C语言的函数实现的. 区别他们之间区别是:API函数是针对操作系统的,C语言运行时函数则是针对C语言本身的. ·1.运行时库就是 C run-time library,是C而非C++语言世界的概念.     取这个名字就是因为你的C程序运行时需要这些库中的函数. ·2.C语言是所谓的“小内核”语言,就其语言本身来说很

C#调用windows API的一些方法

使用C#调用windows API(从其它地方总结来的,以备查询) C#调用windows API也可以叫做C#如何直接调用非托管代码,通常有2种方法: 1.  直接调用从 DLL 导出的函数. 2.  调用 COM 对象上的接口方法 我主要讨论从dll中导出函数,基本步骤如下: 1.使用 C# 关键字 static 和 extern 声明方法. 2.将 DllImport 属性附加到该方法.DllImport 属性允许您指定包含该方法的 DLL 的名称. 3.如果需要,为方法的参数和返回值指定

[译]App Framework 2.1 (1)之 Quickstart (未完待续)

最近有移动App项目,选择了 Hybrid 的框架Cordova  和  App Framework 框架开发. 本来应该从配置循序渐进开始写的,但由于上班时间太忙,这段时间抽不出空来,只能根据心情和兴趣,想到哪写到哪,前面的部分以后慢慢补上. App Framework 前生是是叫 jqMobi 注意大家不要和 jQuery Mobile 混淆了,它们是两个不同的框架,一开始我还真混淆了0.01秒. 这里我先翻译一下Quickstart 部分,一是自己工作上用的上,二是也想顺便练练英文,最关键