⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 teach_sp_62.htm

📁 VC专题教程 -- 第一章 Internet相关开发 打包下载 --- 1.1 如何编写CGI程序 ------ 1.2 一种更亲切的CGI开发系统WinCGI ------ 1.3 利用ISAPI开
💻 HTM
字号:

<!-- LANGUAGE='JavaScript'>write_body();<-->
<!-- LANGUAGE='JavaScript'>write_bar();<-->



<table width=98% cellspacing="0" cellpadding="0" align=center><!--整体框架-->
<tr><td>

<table border=0 width="100%" cellspacing="0" cellpadding="2"><!--标记放置区域-->
<tr>
	<td width="30%" align="center" bgcolor="#8E8E8E" valign=middle><img src=../../img/brand_200_60.gif width=200 height=60 alt="LOGO1"></td>
	<td width="70%" align="center" bgcolor="#8E8E8E" valign=middle><!-- LANGUAGE='JavaScript'>write_ban();<--></td>
</tr>
<tr>
	<td colspan="2" bgcolor="#939393" align=center><font color=white>您当前位置</font> <a href=../../index.htm><font color=white>首页</font></a> <a href=../index.htm><font color=white>开发教程</font></a> <a href=index.htm><font color=white><font class=engul>Visual C++/MFC</font>专题讲座</font></a> <font color=white>6.2 虚存的使用</font> <font color=white><!-- LANGUAGE='JavaScript'>write_command();<--></font></td>
</tr>
</table><!--标记放置区域 END-->

<table border=0 width=100% cellspacing="0" cellpadding="0">
<tr bgcolor="#F4F4F4">
<td><!-- article title begin here-->
<br>
<p align=center><big>6.2 虚存的使用</big>
<p>虚存的分配通过VirtualAlloc函数来完成,对于内存的分配和提交是以页为单位的,如果要求分配的内存大小不为页的整数倍,系统将会加大内存达到页的整数倍,而且会将申请的地址设定在页的边界,所以在申请时尽量按照页来进行申请。
<pre>
LPVOID VirtualAlloc(
  LPVOID lpAddress,        // region to reserve or commit
  SIZE_T dwSize,           // size of region
  DWORD flAllocationType,  // type of allocation
  DWORD flProtect          // type of access protection
);
</pre>
lpAddress 为申请的内存地址,在Win32中你可以自己指定申请内存的地址范围,如果为NULL则由系统分配一段空闲的地址
dwSize 内存大小,以字节为单位
flAllocationType 申请方式,可以取下面的值的组合:
<ul>
<li>MEM_RESERVE 要求系统保留申请的地址,如果申请成功,这段地址就无法再次被申请
<li>MEM_COMMIT 提交已经申请的内存
<li>MEM_TOP_DOWN 在由系统指定地址时要求系统从空闲区域的顶部开始分配,这样可以减少内存碎片
</ul>
flProtect 指定内存的保护方式,可以选用下面的值:
<ul>
<li>PAGE_READONLY 只读
<li>PAGE_READWRITE 读写
<li>PAGE_EXECUTE 执行
<li>PAGE_EXECUTE_READ 执行和读取
<li>PAGE_EXECUTE_READWRITE 执行和读写
<li>PAGE_NOACCESS 不允许任何存取
</ul>
如果函数执行成功会返回要求的地址,否则将会返回NULL。
<p>一段内存在申请后并不能马上使用,如果要使用必须先提交,并且在提交时指定内存的保护方式。对于未申请或已经申请但未提交的内存的任何操作都将会引发异常。
<p>如果要释放或回收已经提交的内存可以使用VirtualFree:
<pre>
BOOL VirtualFree(
  LPVOID lpAddress,   // 地址
  SIZE_T dwSize,      // 大小
  DWORD dwFreeType    // 释放方式 
                      // MEM_DECOMMIT 回收已经提交的虚存 
                      //MEM_RELEASE 释放已经申请的虚存,dwSize这是必须为0
);
</pre>
<p>下面有一些例子可以帮助理解虚存的使用:
<pre>
//eg 1
pMem = VirtualAlloc(NULL,1024*64*2,MEM_RESERVE,0); //申请128K虚存,地址由系统指定
if(pMem) //假设返回值为 0X10000000
{
	pMem2 =VirtualAlloc(pMem + 0X1000,1024*32,MEM_COMMIT,PAGE_READWRITE); //提交32K内存
	if(pMem2)// pMem2=0X10010000
	{
		memcpy(pMem2,p,32*1024);//对内存进行写
		memcpy(p2,pMem2,32*1024);//对内存进行读
		VirtualFree(pMem2,1024*32,MEM_DECOMMIT);//回收
	}
	VirtualFree(pMem,0,MEM_RELEASE);//释放
}
//eg 2
pMem = VirtualAlloc((LPVOID)0X10000000,1024*64*2,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE); 
//由0X10000000开始的128K虚存并同时提交该虚存,保护方式为可以读和写
if(pMem) 
{
	memcpy(pMem,p,32*1024);//对内存进行写
	memcpy(p2,pMem,32*1024);//对内存进行读
	VirtualFree(pMem,1024*64*2,MEM_DECOMMIT);//回收
	VirtualFree(pMem,0,MEM_RELEASE);//释放
}

//eg 3
pMem = VirtualAlloc((LPVOID)0X10000000,1024*64*2,MEM_RESERVE | MEM_COMMIT,PAGE_READ); 
//由0X10000000开始的128K虚存并同时提交该虚存,保护方式为只读
if(pMem) 
{
	memcpy(p2,pMem,32*1024);//对内存进行读
	memcpy(pMem,p,32*1024);//对内存进行写 引发异常,因为该段内存不允许写
	...
}
</pre>
<p>在虚存被提交后可以修改虚存的保护方式,例如在你完成了数据写后可以将内存设置为只读,这样可以放置数据被错误的修改,函数为:
<pre>
BOOL VirtualProtect(
  LPVOID lpAddress,       // 地址
  SIZE_T dwSize,          // 大小
  DWORD flNewProtect,     // 新的保护方式
  PDWORD lpflOldProtect   // 旧的保护方式
);
</pre>
<p>你可以在使用虚存时先取得虚存的状态,函数为:
<pre>
DWORD VirtualQuery(
  LPCVOID lpAddress,                   // 地址
  PMEMORY_BASIC_INFORMATION lpBuffer,  // 返回的数据
  DWORD dwLength                       // 虚存大小
);
typedef struct _MEMORY_BASIC_INFORMATION {
    PVOID BaseAddress; // 查询的地址
    PVOID AllocationBase; // 分配的地址
    DWORD AllocationProtect; // 申请虚存时设定的保护方式
    SIZE_T RegionSize; // 虚存大小
    DWORD State; //当前状态
    //MEM_FREE 还为被申请
    //MEM_RESERVE 已经被申请,但未被提交
    //MEM_COMMIT 已经被提交
    DWORD Protect; // 提交虚存时设定的保护方式
    DWORD Type; // 
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; 
</pre>
<p>本节提供一个例子来帮助大家理解虚存的使用,这个程序具有下面的界面:<br>
<img src=sp_teach_621.gif><br>
你可以点击按钮来执行指定功能,你可以试试看在会提交虚存时进行读写所引发的异常,和在设定为只读时对虚存进行写操作所引发的异常。
<p><a href=sam_sp_62.zip>下载示范代码</a>
<p>此外对虚存可以进行加锁和解锁操作,经过加锁的虚存在不会被系统交换到磁盘上而始终被保存在RAM中。但加锁虚存可能会引起系统性能的下降,所以系统不允许同一进程加锁30页以上虚存,并且如果保护方式为PAGE_NOACCESS 的页。函数为:
<pre>
BOOL VirtualLock(
  LPVOID lpAddress,   // 地址
  SIZE_T dwSize       // 加锁的虚存大小,单位为字节
);
BOOL VirtualUnlock(
  LPVOID lpAddress,   // 地址
  SIZE_T dwSize       // 解锁的虚存大小,单位为字节
);
</pre>
和虚存的分配和提交一样,加锁和解锁也是以页为单位的,即使你加锁2个字节也会引起对所在页的加锁。建议开发过程中如果没有非常的必要不要对虚存进行加锁。
<p>
                  <p align=center><a href=index.htm#charpter6>返回</a></p>
<p align=center><small>版权所有 闻怡洋 <a href=http://www.vchelp.net/><font class=engul>http://www.vchelp.net/<font></font></font></a></small></p>
</small>
	</td></tr><!-- article content end-->
	</table>
</td>
</tr><!-- article title end-->
</table>

</td></tr></table><!--整体框架 END-->



<!-- LANGUAGE='JavaScript'>write_tail();<-->


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -