Windows核心编程<读书笔记十四>虚拟内存一

本文介绍了Windows系统下虚拟内存的概念和技术细节,包括系统信息的获取、虚拟内存的状态及其转换过程,并通过示例代码展示了如何使用API函数GetSystemInfo来获取CPU类型、页面大小等信息。

14 虚拟内存一

【文起】蟹儿回家了,喉咙还有点儿不舒服,舍不得。想跟她一起过春节,奋斗。

虚拟内存其实只是虚拟出来的一个地址空间,不是真正的内存。是为了提高程序加载效率而产生的一种技术。

1、  系统信息:

操作系统的值都是根据主机来的,比如页面大小,分配粒度的大小等。我们可以通过GetSystemInfo函数来检索主机相关的值。可以获取到的值包括:CPU类型以及型号等;CPU页面大小;CPU数目。通过该函数,可以写出如下小程序



void CSystemInfoDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	SYSTEM_INFO sysinfo;
	GetSystemInfo(&sysinfo);

	TCHAR szCpuArch[64] = _T("(unknown)");
	TCHAR szCpuLevel[64] = _T("(unknown)");
	TCHAR szCpuRev[64] = _T("(unknown)");
	TCHAR szBuf[50];
	TCHAR szLine[50] = _T("豆浆&&蟹蟹");

	//获取CPU类型
	switch(sysinfo.wProcessorArchitecture)
	{
	case PROCESSOR_ARCHITECTURE_INTEL://interl
		{
			lstrcpy(szCpuArch,_T("Intel"));
			//CPU型号
			switch (sysinfo.wProcessorLevel)
			{
			case 3:
			case 4:
				wsprintf(szCpuLevel,_T("%80%c86"),sysinfo.wProcessorLevel + '0');
				wsprintf(szCpuRev,_T("%c%d"),HIBYTE(sysinfo.wProcessorRevision) + _T('A'),
					LOBYTE(sysinfo.wProcessorRevision));
				break;
			case 5:
				wsprintf(szCpuLevel,_T("Pentium"));
				wsprintf(szCpuRev,_T("Model %d,Stepping %d"),
					HIBYTE(sysinfo.wProcessorRevision),LOBYTE(sysinfo.wProcessorRevision));
				break;
			case 6:
				wsprintf(szCpuLevel,_T("Pentium Pro or Pentium II"));
				wsprintf(szCpuRev,_T("Model %d,Stepping %d"),
					HIBYTE(sysinfo.wProcessorRevision),LOBYTE(sysinfo.wProcessorRevision));
				break;
			}
			break;
		}

	case PROCESSOR_ARCHITECTURE_ALPHA:
		lstrcpy(szCpuArch,_T("Alpha"));
		wsprintf(szCpuLevel,_T("%d"),sysinfo.wProcessorLevel);
		wsprintf(szCpuRev,_T("Model %c,Pass %d"),
			HIBYTE(sysinfo.wProcessorRevision) + _T('A'),
			LOBYTE(sysinfo.wProcessorRevision));
		break;

	case PROCESSOR_ARCHITECTURE_IA64:
		lstrcpy(szCpuArch,_T("IA-64"));
		wsprintf(szCpuLevel,_T("%d"),sysinfo.wProcessorLevel);
		wsprintf(szCpuRev,_T("Model %c,Pass %d"),
			HIBYTE(sysinfo.wProcessorRevision) + _T('A'),
			LOBYTE(sysinfo.wProcessorRevision));
		break;

	case PROCESSOR_ARCHITECTURE_ALPHA64:
		lstrcpy(szCpuArch,_T("ALPHA-64"));
		wsprintf(szCpuLevel,_T("%d"),sysinfo.wProcessorLevel);
		wsprintf(szCpuRev,_T("Model %c,Pass %d"),
			HIBYTE(sysinfo.wProcessorRevision) + _T('A'),
			LOBYTE(sysinfo.wProcessorRevision));
		break;

	case PROCESSOR_ARCHITECTURE_UNKNOWN:
	default:
		wsprintf(szCpuArch,_T("Unknown"));
	}

	SetDlgItemText(IDC_STATIC_PROCESS_ARCHITECTURE,szCpuArch);
	SetDlgItemText(IDC_STATIC_PROCESS_LEVEL,szCpuLevel);
	SetDlgItemText(IDC_STATIC_PROCESS_REVISION,szCpuRev);
	SetDlgItemInt(IDC_STATIC_PAGE_SIZE,sysinfo.dwPageSize);//CPU页面大小

	_stprintf(szBuf,_T("%p"),sysinfo.lpMinimumApplicationAddress);
	SetDlgItemText(IDC_STATIC_MIN_ADDRESS,szBuf);

	_stprintf(szBuf,_T("%p"),sysinfo.lpMaximumApplicationAddress);
	SetDlgItemText(IDC_STATIC_MAX_ADDRESS,szBuf);

	_stprintf(szBuf,_T("0x%016I64x"),(__int64)sysinfo.dwActiveProcessorMask);
	SetDlgItemText(IDC_STATIC_PROCESSOR_MASK,szBuf);

	SetDlgItemInt(IDC_STATIC_PROCESS_NUMBER,sysinfo.dwNumberOfProcessors);//CPU个数

	SetDlgItemInt(IDC_STATIC_ALLOCATION_GRANULARITY,sysinfo.dwAllocationGranularity);

	wsprintf(&szLine[_tcslen(szLine)],_T("%u"),ul_count++);
	SetDlgItemText(IDC_STATIC_COUNT,szLine);
	
	CDialog::OnTimer(nIDEvent);
}

2、  虚拟内存的状态:

Windows中,可以通过GlobalMemoryStatus检索冠旭当前内存状态的动态信息。这个程序比较简单,不举例。

3、  确定地址空间的状态:

虚拟内存通常是由固定大小的块来实现的,在WIN32中这些块称为“页”,每页大小为4,096字节。在IntelCPU结构中,通过在一个控制寄存器中设置一位来启用分页。启用分页时CPU并不能直接访问内存,对每个地址要经过一个映射进程,通过一系列称作“页表”的查找表把虚拟内存地址映射成实际内存地址。通过使用硬件地址映射和页表WIN32可使虚拟内存即有好的性能而且还提供保护。利用处理器的页映射能力,操作系统为每个进程提供独立的从逻辑地址到物理地址的映射,使每个进程的地址空间对另一个进程完全不可见。

内存页面可以有三种状态:未用(Free)、保留(Reserved)和提交(Committed)。一个未用的页面是指该页面未被保留或是提交,对一个进程来讲一个未用的页面是不可访问的,访问这样的页面将导致访问违例。进程可以要求系统保留一些页面以备后用,系统返回一段保留的地址给进程,但是这些地址同样是不可访问的,进程若想使用这段地址空间,使用必须先提交。只有一个提交的页面才是一个真正可以访问的页面。不过你提交了一个页面,系统并不会马上分配物理页面,只有在该页面第一次被访问到时,系统才会分配页面并初始化。另外,这三个状态的两两之间都是可以相互转化的。

通过下面的函数来查询虚拟内存的状态。

DWORD VirtualQuery(LPCVOID pvAddress, PMEMORY_BASIC_INFORMATION pmbi,DWORD deLength);
DWORD VirtualQueryEx(HANDLE hProcess,LPCVOID pvAddress, PMEMORY_BASIC_INFORMATION pmbi,DWORD deLength);




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值