[转]探索Windows的内存机制

转载 2007年10月14日 14:08:00
内存是操作系统的核心部分,所以我们非常有必要了解内存的分配机制。在DOS下,访问内存的指针是用段地址:偏移量来表示,所有程序共用一个内存空间,由低向高分配内存空间,所以任何程序都可以随便修改内存中的数据,包括不属于自己程序的内存空间和中断向量表。而且所有程序被局限在1M的基本内存(Base Memory)中,不能直接访问扩充内存。对于Windows下的程序来说,它所访问的内存地址不再是真实的。而是虚拟的、独立的全平坦式(flat)的内存空间。如一个32位的程序可访问内存地址是0x00000000到0xffffffff(4G),指针不再存储段地址。所谓独立,指的是当进程A加载到内存0x400000处时,进程B加载到内存的地址时一样是0x400000,两者的地址空间是相互独立的。程序访问内存地址时,由Windows自动换算为真实的内存地址。这样,程序A是无法直接访问程序B的内存空间的,也就提高了系统的稳定性。
    其实,在这4G的内存地址中,我们能使用的内存地址不到一半。我们的程序是无法分配到0x80000000以上的内存地址的,这2G的内存地址都是被系统占用,是只读的。如果一个应用程序企图对大于0x80000000的内存地址进行写操作,则会产生"非法操作"。例如: char *pstr; if(pstr!=NULL) *ptr='a'; 这里声明了一个指针,在没有对其初始化时,它指向0xCCCCCCCC(这里很奇怪不知为什么所有没初始化的变量,其值都为0xCCCCCCCC),所以不为空,因而执行 *pstr=“a” 。由于0xCCCCCCCC在0x80000000以上,产生了一个“非法操作”,这就是有的朋友常犯的错误。
    在Win2000中,用户可以使用0x80000000以上的1G地址(在Boot.ini 中加上参数 /3G) 不过似乎对于普通程序员来说,是没有什么意义的。 Win9x内存中与Win2000的内存分配略有不同。在Win98下,应用程序可使用的内存是从0x400000开始,而在Win2000下,是从0x100000开始。可是加载应用程序时,都是加载到0x400000 。试试这段代码: BYTE buff[0x300]; DWORD dwRead; ReadProccessMemory(GetCurrentProcess(),(PVOID)0x400000,buff,0x300,&dwRead); 请把Buff输出到文件中,你会发现正好是你的应用程序的文件头。 
    Windows的内存分配是以页(page)为单位(与磁盘的扇区很相似),每一页的大小因CPU而异。我们常用的PC机是x86构架,每页为4096字节,可以用GetSystemInfo()函数得到页面大小。一个内存块由多个页面组成。每个页都有一个访问属性: PAGE_NOACCESS 不可访问 PAGE_READONLY 只读 PAGE_READWRITE 读写 PAGE_EXECUTE 可执行 …… 我们可以用: DWORD VirtualQuery( LPCVOID lpAddress, // 内存地址 PMEMORY_BASIC_INFORMATION lpBuffer, // 内存地址信息 DWORD dwLength // lpBuffer 的大小,也就是结构 MEMORY_BASIC_INFORMATION 的大小 ); 来得到某个内存块的状态。使用 VirtualQueryEx() 还可以访问其它进程的内存分配信息。要注意的是这两个函数是得到一个内存块的信息,而不是一个页的信息。在Win9x,当对一个低于0x80000000地址进行写操作时,即使此内存地址为只读(PAGE_READONLY)或是此内存根本就没有分配,Win9x一般也不会报错,这样使得Win9x兼容性好了些,但也使Win9x非常脆弱。在Win2000下则严格遵守页面属性规则,如果你企图对非写属性的内存地址进行操作时,会立刻被中断。这就是为什么很多程序能在Win9x下运行,而转到Win2000下就出现非法操作的原因。虽然我们不能直接读取其它进程的内存空间,但Windows也还是给我们留下了一个后门: ReadProcessMemory()、WriteProcessMemory()。这两个函数可以直接对其它进程的内存进行读写操作。也许你会发现,如果Windows同时启动两次一个相同的应用程序(如同时启动两个Visual Studio),第二次起动的速度明显快于第一次。这是因为,虽然每个程序的内存空间是独立的,但它们有一部分内存是只读的,是可以几个进程共享包括放在0x80000000内存空间以上的系统服务。Windows提供这个功能可以很有效的节省内存空间,提高系统的效率。谈到这里,我们又有问题了,如何在两个进程之间的正常的进行数据交换,而不是用ReadProcessMemory的WriteProcessMemory去强行读写呢? 常用的方法是用MapViewOfFile()把文件映射到内存中,其它进程可以用OpenViewOfFile()来访问,或是用Windows的DDE数据传输协议。还有一种访问是放到DLL中,通过: #pragma data_seg("AllUser") ....//数据 #pragma data_seg() #pragma comment(linker,"/SECTION:AllUser,SRW") // SRW 为共享读写 把某个内存块设置为公用内存,那么就可象使用全局变量一样访问此内存空间。 
    如果有这样一个问题,下面的Struct 在内存中占用多大的字节。 struct{ char a[2]; int b; }abc; 也许你会这样回答,在Windows下Char占一个字节,Int占4个字节,所以是6个字节。其实如果我们用Sizeof得到的大小是8个字节。因为在Windows下对结构变量分配内存空间缺省大小是8的倍数。它不再象DOS一样按本身结构的大小分配,这是由于CPU访问对齐的数据速度要比访问非对齐数据速度要快好几倍。如果你的数据量太大,希望按真实大小对结构分配空间,则可以设置 Project => Setting => C/C++ => Category => Code Generation => struct member alignment 将其设为1就行了。分配非内存对齐的变量同样也会影响执行速度,如: char *pstr=(char *)malloc(5); DWORD *pdw=(DWORD *)(pstr+1); PDW指针指向的就是一个奇数地址,对PDW操作时就很费时。
    小结:对于一个VC程序员来说,很多程序的错误都出现在内存分配上,如未经检查就使用一个空指针等,如果能很好的管理、分配你程序的内存空间,你的程序将会少去一些不必要的错误。 

win7系统32位内存限制完美破解:真正使用4G内存

  • 2015年06月23日 08:47
  • 46KB
  • 下载

Windows 32位程序内存扩展

所有 32 位应用程序都有 4 GB 的进程地址空间(32 位地址最多可以映射 4 GB 的内存)。对于 Microsoft Windows 操作系统,应用程序可以访问 2 GB 的进程地址空间,称为...
  • xiaoyafang123
  • xiaoyafang123
  • 2017-12-28 10:15:41
  • 93

Windows 2008 内存损耗

情景描述: 1.Windows 2008 R2 服务器 32G内存,C#语言编写的文件操作类,每天进行千万级数量的文件读写操作,文件大小本身不大,200KB以内。 2.文件操作类 编写合法,流、对象 ...
  • lxy1106
  • lxy1106
  • 2015-12-15 13:58:55
  • 1544

Windows内存原理与内存管理

1.进程地址空间     Windows为每个进程分配了4GB的虚拟地址空间,让每个进程都认为自己拥有4GB的内存空间,4GB怎么来的? 32位 CPU可以取地址的空间为2的32次方,就是4GB. ...
  • dongpanshan
  • dongpanshan
  • 2015-07-03 16:17:56
  • 1546

dll占的究竟是谁的空间?——浅谈Windows内存机制

近来工作比较空闲,所以就上csdn.net看看帖子什么的,两个多月前,我在VC/MFC板块中发了这么一个帖子:dll占的究竟是谁的空间?详细参考: http://topic.csdn.net/u/20...
  • guogangj
  • guogangj
  • 2008-04-08 17:00:00
  • 6880

全面介绍Windows内存管理机制及C++内存分配实例(一):进程空间

本文背景:在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用;根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制。本文目...
  • yeming81
  • yeming81
  • 2008-01-16 06:54:00
  • 20790

Windows 内存详解(三)Windows内存管理

本文主要内容: 1.基本概念:物理内存、虚拟内存;物理地址、虚拟地址、逻辑地址;页目录,页表 2.Windows内存管理 3.CPU段式内存管理 4.CPU页式内存管理   一、基本概念 ...
  • woddle
  • woddle
  • 2015-04-28 16:27:05
  • 1167

全面介绍Windows内存管理机制及C++内存分配实例

转自:http://blog.csdn.net/yeming81/article/details/2046193 本文基本上是windows via c/c++上的内容,笔记做得不错。。 本文背景...
  • vsooda
  • vsooda
  • 2013-05-30 09:44:10
  • 22278

Windows内存管理机制及C++内存分配

  • 2011年06月21日 10:38
  • 103KB
  • 下载

[转]探索Windows的内存机制

内存是操作系统的核心部分,所以我们非常有必要了解内存的分配机制。在DOS下,访问内存的指针是用段地址:偏移量来表示,所有程序共用一个内存空间,由低向高分配内存空间,所以任何程序都可以随便修改内存中的数...
  • wuhuiran
  • wuhuiran
  • 2007-10-14 14:08:00
  • 705
收藏助手
不良信息举报
您举报文章:[转]探索Windows的内存机制
举报原因:
原因补充:

(最多只允许输入30个字)