《windows核心编程》读书笔记——内存体系结构

来源:互联网 发布:json格式化工具下载 编辑:程序博客网 时间:2024/05/17 22:05

         操作系统所使用的内存体系结构是理解操作系统如何运作的关键,充分理解系统管理内存的方式,往往有助于我们快速而准确地找到理解内存问题的实质。

 

         每个进程都有自己的虚拟地址空间,对32位进程来说,这个地址空间的大小为4GB;对64位进程来说,这个地址空间的大小为16EB。每个进程都有自己专有的地址空间,当进程中的各线程运行时,它们只能访问属于该进程的内存。线程既看不到属于其他进程的内存,也无法访问它们。虽然应用程序有这么大的地址空间可用,但是要记住这只是虚拟的地址空间——不是物理存储器。

         下图是32Windows内核和64Windows内核的分区信息。

Partition

x86 32-Bit Windows

x86 32-Bit Windows with 3 GB   User-Mode

x64 64-Bit Windows

IA-64 64-Bit Windows

NULL-Pointer Assignment

0x00000000

0x00000000

0x00000000'00000000

0x00000000'00000000

0x0000FFFF

0x0000FFFF

0x00000000'0000FFFF

0x00000000'0000FFFF

User-Mode

0x00010000

0x00010000

0x00000000'00010000

0x00000000'00010000

0x7FFEFFFF

0xBFFEFFFF

0x000007FF'FFFEFFFF

0x000006FB'FFFEFFFF

64-KB Off-Limits

0x7FFF0000

0xBFFF0000

0x000007FF'FFFF0000

0x000006FB'FFFF0000

0x7FFFFFFF

0xBFFFFFFF

0x000007FF'FFFFFFFF

0x000006FB'FFFFFFFF

Kernel-Mode

0x80000000

0xC0000000

0x00000800'00000000

0x000006FC'00000000

0xFFFFFFFF

0xFFFFFFFF

0xFFFFFFFF'FFFFFFFF

        

         空指针分区:从0x000000000x0000FFFF的闭区间,保留该分区的目的是为了帮助程序员捕获对空指针的赋值。如果进程中的线程试图读取或写入位于这一分区内的内存地址,就会引发访问违规。没有任何办法可以让我们分配到位于这一地址区间内的虚拟内存。

         用户模式分区:这一分区是进程地址空间的驻地。用户无法通指针来读取、写入或以任何方式访问其他进程的这一分区的数据。(对于LARGEADDRESSAWAR开关这里不讨论,请参考MSDN)。

         内核模式分区:这一分区是操作系统代码的驻地。与线程高度、内存管理、文件系统支持、网络支持以及设备驱动程序相关的代码都载入到该分区。驻留在这一分区内的任何东西为所有进程共有。如果一个应用程序试图读取或写入位于这一分区中的内存地址,会引发访问违规。

 

         以下两段是我根据英语原文的意思,加上我的理解写出来的,译著讲的很糊涂以致于会让人产生误解。

         当程序预订一个地址空间区域时,系统在查找可用地址时会确保的起始地址正好是分配粒度的整数倍。目前所有CPU使用的粒度都是64K

         当程序在地址空间区域上预订一个地址空间块时,系统会确保块的大小上调到系统页面大小的整数倍。不同CPU的页面大小可能会不一样,x86x64系统使用的页面大小为4KB,而IA-64系统使用的页面大小为8KB

 

         通过使用磁盘上的文件(页交换文件)可以扩展可用物理存储器的大小,也就是使用虚拟内存技术。使用虚拟内存会引发换页错误,如果过多的换页会损害硬盘并且使程序运行变慢。

         当把一个程序位于硬盘上的文件映像(exedll文件)用作地址空间对应的物理存储器时,我们称这个文件映像为内存映射文件(memory mapped file)

 

         物理存储器页面的保护属性列表,另外还有三个特殊的访问保护属性在这里没列出。如果同时给和物理存储器指定了保护属性,那么以物理存储器指定的为准。

Protection Attribute

Description

PAGE_NOACCESS

Attempts to read from, write to, or execute code in this page raise an  access violation.

PAGE_READONLY

Attempts to write to or execute code in this page raise an access

PAGE_READWRITE

Attempts to execute code in this page raise an access violation.

PAGE_EXECUTE

Attempts to read or write memory in this page raise an access violation.

PAGE_EXECUTE_READ

Attempts to write to memory in this page raise an access violation.

PAGE_EXECUTE_READWRITE

There is nothing you can do to this page to raise an access violation.

PAGE_WRITECOPY

Attempts to execute code in this page raise an access violation.  Attempts to write to memory in this page cause the system to paging file).

PAGE_EXECUTE_WRITECOPY

There is nothing you can do to this region to raise an access violation.  Attempts to write to memory in this page cause the system to give the process  its own private copy of the page (backed by the paging file).

 

         进程写时复制不修改原始页面的保护属性,只需要把共享数据复制到自己进程的页交换文件空间,再修改进程的页面表。这些步骤由系统完成。

 

         内存区域类型:

Type

Description

Free

The region's virtual addresses are not backed by any storage. This  address space is not reserved; the application can reserve a region either at  the shown base address or anywhere within the free region.

Private

The region's virtual addresses are backed by the system's paging file.

Image

The region's virtual addresses were originally backed by a memory-mapped  image file (such as an .exe or a DLL file). The virtual addresses might not  be backed by the image file anymore. For example, when a global variable in a  module's image is written to, the copy-on-write mechanism backs the specific  page from the paging file instead of the original image file.

Mapped

The region's virtual addresses were originally backed by a memory-mapped  data file. The virtual addresses might not be backed by the data file  anymore. For example, a data file might be mapped using copy-on-write protection.  Any writes to the file cause the specific pages to be backed by the paging  file instead of the original data.

         注意Free类型的区块的基址是无效的,通常为0

         由于windowsPE文件映射一进程的虚拟地址空间时,每一段必须另起一页,而且起始地址必须是系统页面大小的整数倍,这使PE文件所需要的虚拟地址空间的大小一般来说要大于文件本身的大小。