友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
喜书网 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

C语言实例教程(PDF格式)-第25章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!






每一个进程的虚拟地址空间都要比所有进程可用的物理内存RAM               (随 

机存取存储器)的总合大得多。为了增加物理存储的大小,内核使用 

磁盘作为额外的存储空间。对于所有正在执行的进程来说,总的存储 

空间的量是物理内存RAM和磁盘上可以为页面文件所用的自由空间的 

总合,这里页面文件指用来增加物理存储空间的磁盘文件。每个进程 

物理存储空间和虚拟地址 (也称为逻辑地址)空间以页的形式来组织, 

页是一种内存单元,其大小依赖于宿主计算机的类型。对于x86计算 

机来说,宿主页大小为4KB,但我们不能假定对有所有运行Windows操 

作系统的计算机,其页大小均为4KB。  



为了使内存管理具有最大的灵活性,内核可以将物理内存中的页移入 

或移出磁盘上的页面文件。当一个页被移入物理内存时,内核更新受 

到影响的进程的页映射。将内核需要物理内存空间时,它将物理内存 

中最近最少使用的页移入页面文件。对于应用程序来说,内核对物理 

内存的管理是完全透明的,应用程序只对它自己的虚拟地址空间进行 

操作。   



在进程虚拟地址空间中的页可以具在表所列的状态之一:  



              表3。 4 虚拟地址空间中页的不同状态  



     状态      说明  



     空闲(Free)  空闲页是当前不可用,但可以被占用或保留的页。  



     保留      保留页是进程的虚拟地址空间中为将来使用所保留的 

     (Reserved)  页。进程不可以存取保留页,并且也没有为保留页分配 

             物理存储。保留页保留虚拟地址中的一段以使得它们不 

             可以被随后的其它分配操作(如malloc和LocalAlloc之类 

             的函数等)所使用。一个进程可以使用VirtualAlloc函数 

             在其地址空间中保留页面,然后再占用这些保留页。最 

             后使用VirtualFree函数释放它们。  



     占用      已被占用的页是那些已分配了物理存储 (在内存中或磁盘 

     (mitted)  上)的页。占用页可以被禁止进行存取,或允许只读存 

             取,或允许读写存取。进程可以使用VirtualAlloc函数 

             分配占用页。GlobalAlloc和LocalAlloc函数分配允许读 


…………………………………………………………Page 154……………………………………………………………

            写存取的占用页。占用页可以使用VirtualFree函数进行 

            释放,函数VirtualFree释放页的存储空间,并将其状态 

            改变为保留。  



进程可以使用函数GlobalAlloc和LocalAlloc来分配内存。在Win32  

API的32位线性环境中,本地堆和全局堆并没有区别,因此,使用这 

两个函数来分配内存对象也没有任何区别。  



由GlobalAlloc和LocalAlloc函数分配的内存对象位于私有的占用页 

中,这些页允许进行读写存取。私有内存不可以为其它进程所访问。 

与在Windows       3。x中不同,使用带有GMEM_DDESHARE标志的 

GlobalAlloc函数分配的内存事实上并没有被全局共享。保留该标志 

位仅是为了向前兼容和为一些应用程序增强动态数据交换 (DDE, 

dynamic data exchange)的性能而使用。应用程序如果因其它 目的需 

要共享内存,那么必须使用文件映射对象。多个进程可以通过映射同 

一个文件映射对象的视来提供命名共享内存。我们在这里将不讨论文 

件映射和共享内存的问题。  



通过使用函数GlobalAlloc和LocalAlloc,可以分配能够表示为32位 

的任意大小的内存块,所受的唯一限制是可用的物理内存,包括在磁 

盘上的页面文件中的存储空间。这些函数,和其它操作全局和本局内 

存对象的全局和本地函数一起被包含在Win32  API中,以和Windows的 

16位版本相兼容。但是,从16位分段内存模式到32位虚拟内存模式的 

转变将使得一些函数和一些选项变得不必要甚至没有意义。比如说, 

现在不再和近指针和远指针的区别,因为无论在本地还是在全局进行 

分配都将返回32位虚拟地址。   



函数GlobalAlloc和LocalAlloc都可以分配固定或可移动的内存对 

象。可移动对象也可以被标记为可丢弃的(discardable)。在早期的 

Windows版本中,可移动的内存对象对于内存管理非常之重要,它们 

允许系统在必要时压缩堆以为其它内存分配提供可用空间。通过使用 

虚拟内存,系统能够通过移动物理内存页来管理内存,而不影响使用 

这些页的进程的虚拟地址。当系统移动一个物理内存页时,它简单的 

将进程的虚拟页映射到新的物理页的位置。可移动内存在分配可丢弃 

内存仍然有用。当系统需要额外的物理存储时,它使用一种称作 “最 

近最少使用”的算法来释放非锁定的可丢弃内存。可丢弃内存可以用 

于那些不是经常需要和易于重新创建的数据。  



当分配固定内存对象时,GlobalAlloc和LocalAlloc返回32位指针, 

调用线程可以立即使用该指针来进行内存存取。对于可移动内存,返 

回值为一个句柄。为了得到一个指向可移动内存的指针,调用线程可 


…………………………………………………………Page 155……………………………………………………………

以使用GlobalLock和LocalLock函数。这些函数锁定内存使得它不能 

够被移动或丢弃,除非使用函数GlobalReAlloc或LocalReAlloc对内 

存对象进行重新分配。已锁定内存对象的内存块保持锁定状态,直至 

锁定计数减到0,这时该内存块可以被移动或丢弃。  



由GlobalAlloc和LocalAlloc所分配的内存的实际大小可能大于所要 

求的大小。为了得到已分配的实际内存数,可以使用函数GlobalSize 

和LocalSize。如果总分配量大于所要求的量,进程则可以使用所有 

的这些量。'  



函数GlobalReAlloc和LocalReAlloc以字节为单位改变由GlobalAlloc 

和LocalAlloc函数分配内存对象的大小或其属性。内存对象的大小可 

以增大,也可以减小。  



函数GlobalFree和LocalFree用于释放由GlobalAlloc、LocalAlloc、 

GlobalReAlloc或LocalReAlloc分配的内存。  



其它的全局和本地函数包括GlobalDiscard、LocalDiscard、 

GlobalFlags、LocalFlags、GlobalHandle和LocalHandle。 

GlobalDiscard和LocalDiscard用于丢弃指定的可丢弃内存对象,但 

不使其句柄无效。该句柄可能通过函数GlobalReAlloc或 

LocalReAlloc与新分配的内存块相关联。函数GlobalFlags或 

LocalFlags返回关于指定内存对象的信息。这些住处包括对象的锁定 

计数以及对象是否可丢弃或是否已被丢弃。函数GlobalHandle或 

LocalHandle返回与指定指针相关联的内存对象的句柄。  



Win32进程可以完全的使用标准的C库函数malloc、free等来操作内 

存。在Windows的早期版本中使用这些函数,将可能带来问题隐患, 

但是使用Win32   API的应用程序中则不会。举例来说,使用malloc分 

配固定指针将不能使用可移动内存的优点。由于系统可以通过移动物 

理内存页来自由的管理内存,而不影响虚拟地址,因此内存管理将不 

再成为问题。类似的,远指针和近指针之间不再有差别。因此,除非 

你希望使用可丢弃内存,否则完全可以将标准的C库函数用于内存管 

理。  



Win32   API提供了一系列的虚拟内存函数来操作或决定虚拟地址空间 

中的页的状态。许多应用程序使用标准的分配函数GlobalAlloc、 

LocalAlloc、malloc等就可以满足其需要。然而,虚拟内存函数提供 

了一些这些标准分配函数所不具有的功能,它们可以进行下面的这些 

操作:  


…………………………………………………………Page 156……………………………………………………………

 l 保留进程虚拟地址空间中的一段 保留地址空间并不为它们分配物 

  理存储,而只是防止其它分配操作使用这段空间。它并不影响其 

  它进程的虚拟地址空间。保留页防止了对物理存储的不必要的浪 

  费,然而它允许进程为可能增长的动态数据结构保留一段地址空 

  间,进程可以在需要的时候为这些空间分配物理存储。  



 l 占用进程虚拟地址空间中的保留页的一部分,以使得物理存储 (无 

  论是RAM还是磁盘空间)只对正在进行分配的进程可用。  



 l 指定允许读写存取、只读存取或不允许存取的占用页区域。这和 

  标准的分配函数总是分配允许读写存取的页不同。  



 l 释放一段保留页,使得调用线程在随后的分配操作中可以使用这 

  段虚拟地址。  



 l 取消对一段页的占用,释放它们的物理存储,使它们可以其它进 

  程在随后的分配中使用。  



 l 在物理内存RAM中锁定一个或多个占用页,以免系统将这些页交换 

  到页面文件中。  



 l 获得关于调用线程或指定线程的虚拟地址空间中的一段页的信 

  息。  



 l 改变调用线程或指定线程的虚拟地址空间中指定占用页段的存取 

  保护。  



虚拟内存函数对内存页进行操作。函数使用当前计算机的页大小来对 

指定的大小和地址进行舍入。  



可以使用函数GetSystemInfo来获得当前计算机的页大小。  



函数VirtualAlloc完成以下操作:  



 l 保留一个或多个自由页。  



 l 占用一个或多个保留页。  



 l 保留并占用一个或多个自由页。  



你可以指针所保留或占用的页的起始地址,或者让系统来决定。函数 

将指定的地址舍入到合适的页边界。保留页是不可访问的,但占用页 

可以使用标志位PAGE_READWRITE、PAGE_READONLY和PAGE_NOACCESS来 


…………………………………………………………Page 157……………………………………………………………

分配。当页被占用时,从页面文件中分配存储空间,每个页仅在第一 

次试图对其进行读写操作时被初始化并加载到物理内存中。可以用一 

般的指针引用来访问由VirtualAlloc函数 占用的页。  



函数VirtualFree完成下面的操作:  



  l 解除对一个或多个页的占用,改变其状态为保留。解除对页的战 

   胜释放与之相关的物理存储,使其为其它进程可用。任何占用页 

   块都可以被解除占用。  



  l 释放一个或多个保留页块,改变其状态为 自由。释放页块使这段 

   保留空间可以为进程分配空间使用。保留页只能通过释放由函数 

   VirtualAll
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!