Windows内存体系结构

个人觉得比较重要的两个概念:

一、每个进程的用户模式地址空间都是独立私有的,用VS调试时输入的“内存地址”是地址空间值,其对应的真实物理地址对我们是透明的(MMU负责虚拟地址映射为物理地址内核模式分区是共有的。应用程序是在用户模式下(Ring 3),驱动为内核模式(Ring 0)。                               (Ring 0 权限获取)

二、CPU只能访问内存上的数据。所以当要访问地址空间的一个数据时,要查看这个数据是否在内存上,不在则需要从页交互文件中复制到内存上。(核心编程上有流程图)。


---------------------------------------------------------------------------------------------------------------------

进程的虚拟地址空间间分为四个部分:空指针赋值分区,用户模式分区(对用户可用),64KB禁入分区,内核模式分区。

1.虚拟内存查询就几个函数调用。有个NUMA(非统一内存访问)机器,没怎么看。

2.VirtuaAlloc: 

 默认是从“页交互文件”中调拨物理存储器。

大页面支持(MEM_LARGE_PAGE)和AWE(MEM_PHYSICAL)是从“物理内存”

3.线程栈:

默认1MB(有人说跟编译器和系统有关,我32位WIN7,VS2010上是1MB),并在高地址调拨两个页面。有个防护属性对栈满保护。书上栈下溢的代码有点问题补上:(但对于栈后内存已预定区域的读写属性改不过来,不知道为啥~没权限?)

void CsixteenDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	BYTE aBytes[0x10]={"1234567"};
	//Figure out where the stack is in the virtual address space
	MEMORY_BASIC_INFORMATION mbi;
	SIZE_T size = VirtualQuery(aBytes,&mbi,sizeof(mbi));

	//Allocate a block of memory just after the 1MB stack
	SIZE_T s = (SIZE_T)mbi.AllocationBase + 1024 *1024;
	PBYTE pAddress = (PBYTE)s;
	SIZE_T interval  = s - (SIZE_T)aBytes;
	size = VirtualQuery(pAddress,&mbi,sizeof(mbi));
	BYTE * pBytes = NULL;
	DWORD dOldProtect = 0; 
	if(mbi.State == MEM_COMMIT)
	{
		::OutputDebugStringA("线程栈后地址空间已经预定\r\n");
		if(mbi.Protect != PAGE_READWRITE)
		{
			//修改页保护属性不能跨区域,要分多次调用
			//改变线程栈后一个页面的保护属性
			if(!VirtualProtect(pAddress,2*1024,PAGE_READWRITE,&dOldProtect))
			{
				::OutputDebugStringA("修改页保护属性为可读可写失败\r\n");
				return;
			}
		}
	}
	else
	{
		pBytes = (BYTE *)VirtualAlloc(pAddress,0x10,MEM_COMMIT| MEM_RESERVE, PAGE_READWRITE);
	}

	//Trigger an unnoticeable stack underflow
	aBytes[interval] = 1; //Write in the allocated block,past the stack

	//还原保护属性
	if(dOldProtect != 0)
	{
		DWORD temp =0;
		VirtualProtect(pAddress,4*1024,dOldProtect,&temp);
	}
	//释放地址空间
	if(pBytes != NULL)
	{
		VirtualFree(pAddress,0,MEM_RELEASE);
	}

}
4.内存映射文件:

要提到“写时复制”:多实例运行,对于需要写时复制保护的页面会在页交换文件挑拨存储器,但只有在一个实例真正写入其中一个页面时才使用到。个人觉得“写时复制”就是保护数据的独立性。

作用:进程间通信,创建自定义段,#pragma comment(linker,"/SECTION:Shared,RWS")设置共享。

大文件操作

5.堆:

自定义堆的好处:对组件进行保护(一个结构处理代码有缺陷可能会覆盖掉另一个结构的内容区),

更有效的内存管理,使内存访问局部化(减少内存与磁盘之间的交换),避免线程同步的开销,快速释放。

另外:页保护属性是针对页的。可以用来保护数据,定位一个很难发现的缺陷(谁来举个例子加深下印象)


最后给个图:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值