CHAPTER 10 Memory Management
In this chapter, you’ll learn how Windows implements virtual memory and how it manages the subset of virtual memory kept in physical memory. We’ll also describe the internal structure and components that make up the memory manager, including key data structures and algorithms. Before examining these mechanisms, we’ll review the basic services provided by the memory manager and key concepts such as reserved memory versus committed memory and shared memory.
Introduction to the Memory Manager
By default, the virtual size of a process on 32-bit Windows is 2 GB. If the image is marked specifically as large address space aware, and the system is booted with a special option (described later in this chapter), a 32-bit process can grow to be 3 GB on 32-bit Windows and to 4 GB on 64-bit Windows.
The process virtual address space size on 64-bit Windows is 7,152 GB on IA64 systems and 8,192 GB on x64 systems. (This value could be increased in future releases.)
As you saw in Chapter 2, “System Architecture,” in Part 1 (specifically in Table 2-2), the maximum amount of physical memory currently supported by Windows ranges from 2 GB to 2,048 GB, depending on which version and edition of Windows you are running. Because the virtual address space
might be larger or smaller than the physical memory on the machine, the memory manager has two primary tasks:
■ Translating, or mapping, a process’s virtual address space into physical memory so that when a thread running in the context of that process reads or writes to the virtual address space, the correct physical address is referenced. (The subset of a process’s virtual address space that is
physically resident is called the working set. Working sets are described in more detail later in this chapter.)
■ Paging some of the contents of memory to disk when it becomes overcommitted—that is, when running threads or system code try to use more physical memory than is currently available— and bringing the contents back into physical memory when needed.
In addition to providing virtual memory management, the memory manager provides a core set of services on which the various Windows environment subsystems are built. These services include memory mapped files (internally called section objects), copy-on-write memory, and support for applications using large, sparse address spaces. In addition, the memory manager provides a way for a process to allocate and use larger amounts of physical memory than can be mapped into the process virtual address space at one time (for example, on 32-bit systems with more than 3 GB of physical memory). This is explained in the section “Address Windowing Extensions” later in this chapter.
除了提供虚拟内存管理服务外,内存管理器还为构建在它上层的各种 windows 环境子系统提供一组核心服务;这些服务包括内存映射文件(在 windows 中叫做 section 对象 ),写时复制内存,以及支持应用程序使用大规模,稀疏(非连续)的地址空间。此外,内存管理器提供了一种方法,给进程一次性分配和使用大量的物理内存,可以超过映射入进程虚拟地址空间的上限(例如,在 32 位系统上,可以分配多于3GB 的物理内存,这就超过了进程的 3GB 虚拟内存上限)。在本章后面的“Address Windowing Extensions”(地址窗口扩展?)部分,将对其进行解释。
Note
There is a Control Panel applet that provides control over the size, number, and locations of the paging files, and its nomenclature suggests that “virtual memory” is the same thing as the paging file. This is not the case. The paging file is only one aspect of virtual memory. In fact, even if you run with no page file at all, Windows will still be using virtual memory. This distinction is explained in more detail later in this chapter.
Memory Manager Components
The memory manager is part of the Windows executive and therefore exists in the file Ntoskrnl.exe.
No parts of the memory manager exist in the HAL. The memory manager consists of the following components:
■ A set of executive system services for allocating, deallocating, and managing virtual memory,most of which are exposed through the Windows API or kernel-mode device driver interfaces
■ A translation-not-valid and access fault trap handler for resolving hardware-detected memory management exceptions and making virtual pages resident on behalf of a process
内存管理器的组件
内存管理器是 windows 执行体的一部分,因此它存在于文件 Ntoskrnl.exe 之中。内存管理器没有任何部分是位于 HAL(译注:硬件抽象层)中的。内存管理器由下列组件构成:
■ 一组用于分配,释放,以及管理虚拟内存的执行体系统服务,其中多数通过Windows API或者内核模式设备驱动接口对外暴露;
■ 一个翻译无效和访问错误陷阱处理程序,用于解决硬件探测到的内存管理异常,以及代表一个进程,让它的部分虚拟页面驻留在物理内存中;(这句翻译的不好,原文是A translation-not-valid and access fault trap handler for resolving hardware-detected memory management exceptions and making virtual pages resident on behalf of a process。谁知道怎么翻译较好?)
■ Six key top-level routines, each running in one of six different kernel-mode threads in the System process (see the experiment “Mapping a System Thread to a Device Driver,” which shows how to identify system threads, in Chapter 2 in Part 1):
■ 6个关键的顶级(译注:这里应该是指线程调度的优先级,数值越大,优先级越高)例程,每个例程作为 System 进程中6种不同的内核模式线程之一运行(回顾上册第2章的实验“将一个系统线程映射到一个设备驱动”,该实验展示了辨别系统线程的方法):
(译注:System 进程的 PID 为 4,它是一种特殊线程的宿主,这种特殊线程只能在内核模式下运行,称为“内核模式系统线程”,这意味着,它们没有用户空间地址,所以这些线程临时申请任何存储空间时,通常会从内核模式堆/系统内存池中分配,具体参考第二部分译文。此外,各种执行体组件中的例程,以及设备驱动程序,都可以通过由执行体组件——进程/线程管理器——导出的 PsCreateSystemThread() 例程,来在 System 进程中创建系统线程——这仅仅是默认的行为,换言之,该例程支持指定其它进程作为要创建的系统线程宿主。通过 sysinternal 的进程浏览器工具,查看 System 进程的属性,选择“Thread”标签,可以看到当前运行在其中的所有系统线程,正常情况下应该有100多个左右;按照每次采样间隔的上下文切换次数排序。即 CSwitch Delta,可以列出因上下文切换导致占用最多 CPU 时钟周期的系统线程;如下图所示,线程的启动地址以 ntkrnlpa.exe! 开头的,一般就是各种执行体组件通过 PsCreateSystemThread() 例程创建的系统线程;而线程的启动地址以 .sys 后缀开头的,表示由相应的设备驱动程序创建的系统线程。 )
(译注:需要特别指出,由于某种原因,你使用进程浏览器查看 System 进程中的系统线程时,可能无法找到下文描述的 6 个系统线程,例如平衡集管理器,即 KeBalanceSetManager() ,如果你要进一步研究这个线程的内部逻辑,来验证原文对它的描述是否正确,则可以使用 KD.exe/Windbg.exe 的 uf 调试器命令,反汇编该例程中的机器代码,当然,也可以使用 IDA PRO 打开 ntkrnlpa.exe 映像,然后分析相应的位置,如下图所示
1. The balance set manager (KeBalanceSetManager, priority 16). It calls an inner routine, the working set manager (MmWorkingSetManager), once per second as well as when free memory falls below a certain threshold. The working set manager drives the overall memory management policies, such as working set trimming, aging, and modified page writing.
1. balance set manager(KeBalanceSetManager,平衡集管理器,优先级16)。它调用一个内部例程,叫做
working set manager
(MmWorkingSetManager,工作集管理器),后者每秒被调用一次;
(注意例程名称前缀的暗示:平衡集管理器以 Ke 开头,表明它是在更底层的内核中实现的;工作集管理器以 Mm 开头,表明它是在执行体组件——内存管理器——中实现的)。
此外,当可用内存低于某个阈值时,它也会被调用。工作集管理器会驱动整体的内存管理策略,例如工作集大小微调(裁剪),增加页面的使用年龄(译注:用于页面置换算法确定最近最少使用的页面,作为牺牲页换出内存),并且,如果牺牲页已被修改过,先将原修改数据写回磁盘上的交换空间(分页文件),然后再将该页面用于存储新数据。这个过程由 MiModifiedPageWriter() 例程负责,参见下文
2. The process/stack swapper (KeSwapProcessOrStack, priority 23) performs both process and kernel thread stack inswapping and outswapping. The balance set manager and the thread-scheduling code in the kernel awaken this thread when an inswap or outswap operation needs to take place.
2. process/stack swapper(KeSwapProcessOrStack,进程/栈交换器,优先级23)。执行进程与内核线程栈的换入换出操作。平衡集管理器与内核中的线程调度代码(译注:即操作系统调度器;在 Linux 和UNIX上,任务调度通常以进程为单位,而 windows 则支持线程粒度的调度)在需要发生进程或者内核线程栈的换入和换出操作时,就会唤醒这个线程。(译注:在 UNIX 变体如 4.3 BSD 上,执行相同任务的是一个叫做
swapper 的系统进程,通常在系统的空闲物理页框即物理内存不足,或者某些进程长时间没有获得调度从而变成非活动进程时,swapper 进程和 windows 的
process/stack swapper 线程被唤醒,将这些进程换出内存,从而释放空间。KeSwapProcessOrStack() 例程的操作会影响到线程的调度状态改变,例如,假设一个线程准备好执行,但它的内核栈[内核模式线程的情况]或调用栈/所属进程[用户模式线程的情况],被换出了内存,则该线程进入转换状态。一旦这些栈或所属进程被换回至内存中,该线程进入就绪状态。关于对线程调度状态的讨论,请参考本书上册第五章的 5.7 节——线程调度)
3. The modified page writer (MiModifiedPageWriter, priority 17) writes dirty pages on the modified list back to the appropriate paging files. This thread is awakened when the size of the modified list needs to be reduced.
4. The mapped page writer (MiMappedPageWriter, priority 17) writes dirty pages in mapped files to disk (or remote storage). It is awakened when the size of the modified list needs to be reduced or if pages for mapped files have been on the modified list for more than 5 minutes. This second modified page writer thread is necessary because it can generate page faults that result in requests for free pages. If there were no free pages and there was only one modified page writer thread, the system could deadlock waiting for free pages.
5. The segment dereference thread (MiDereferenceSegmentThread, priority 18) is responsible for cache reduction as well as for page file growth and shrinkage. (For example, if there is no virtual address space for paged pool growth, this thread trims the page cache so that the paged pool used to anchor it can be freed for reuse.)
5. segment dereference thread (MiDereferenceSegmentThread,暂译为“内存段解引用线程”,优先级 18)。负责减少系统高速缓存数量(译注:这里不是CPU芯片内的硬件 L1~L3 cache,应该是指 windows 将磁盘上的分页文件用作物理内存的高速缓存这一概念)以及负责分页文件的增长和收缩。(例如,若没有虚拟地址空间可用于分页池增长,该线程将裁剪页面缓存的大小——解引用部分页面缓存——这样就能够释放页面缓存占用的虚拟内存并重用于分页池)(译注:这句也不太好翻译,原文是For example, if there is no virtual address space for paged pool growth, this thread trims the page cache so that the paged pool used to anchor it can be freed for reuse )
6. The zero page thread (MmZeroPageThread, base priority 0) zeroes out pages on the free list so that a cache of zero pages is available to satisfy future demand-zero page faults.
Unlike the other routines described here, this routine is not a top-level thread function but is called by the top-level thread routine
Phase1Initialization. MmZeroPageThread never returns to its caller, so in effect the Phase 1 Initialization thread becomes the zero page thread by calling this routine. Memory zeroing in some cases is done by a faster function called MiZeroInParallel. See the note in the section “Page List Dynamics” later in this chapter.
Each of these components is covered in more detail later in the chapter.
零页线程从不返回(到它的调用者),因此实际上,Phase1 初始化线程函数(在最后)通过调用此例程变成零页线程。内存清零操作有时候通过一个叫“MiZeroInParallel”的函数完成,其速度更快。更多细节请查看本章后面的“Page List Dynamics”(动态页列表?直译。。。);
本章后面会涵盖上述 6 个内存管理器组件的更多细节。
(译注:为了避免只见树木不见林的弊端,下图给出内存管理器在整个Windows系统架构中的位置。注意,为求简洁,这张系统架构图省略了许多用户模式子系统DLL,内核模式组件,TCP/IP协议栈如tcpip.sys等。重点突出函数调用的轨迹,以及模块之间的依赖性。完整的系统架构图,各位可以参考本书上册第2章“关键的系统组件”一节)
Internal Synchronization
Like all other components of the Windows executive, the memory manager is fully reentrant and supports simultaneous execution on multiprocessor systems—that is, it allows two threads to acquire resources in such a way that they don't corrupt each other's data. To accomplish the goal of being fully reentrant, the memory manager uses several different internal synchronization mechanisms, such as spinlocks, to control access to its own internal data structures. (Synchronization objects are discussed in Chapter 3, “System Mechanisms,” in Part 1.)
Some of the systemwide resources to which the memory manager must synchronize access include:
■ Dynamically allocated portions of the system virtual address space
■ System working sets
■ Kernel memory pools
■ The list of loaded drivers
■ The list of paging files
■ Physical memory lists
■ Image base randomization (ASLR) structures
■ Each individual entry in the page frame number (PFN) database
Per-process memory management data structures that require synchronization include the working set lock (held while changes are being made to the working set list) and the address space lock (held whenever the address space is being changed). Both these locks are implemented using pushlocks.
Examining Memory Usage
The Memory and Process performance counter objects provide access to most of the details about system and process memory utilization. Throughout the chapter, we'll include references to specific performance counters that contain information related to the component being described. We've included relevant examples and experiments throughout the chapter.
One word of caution, however:
different utilities use varying and sometimes inconsistent or confusing names when displaying memory information. The following experiment illustrates this point. (We'll explain the terms used in this example in subsequent sections.)
EXPERIMENT: Viewing System Memory Information
The Performance tab in the Windows Task Manager, shown in the following screen shot, displays basic system memory information. This information is a subset of the detailed memory information available through the performance counters. It includes data on both physical and virtual memory usage.
The following table shows the meaning of the memory-related values.
下表解释任务管理器中使用的内存相关术语的含义:
Memory bar histogram
内存的条柱形图
Bar/chart line height shows physical memory in use by Windows (not available as a performance counter). The remaining height of the graph is equal to the Available counter in the Physical Memory section,
described later in the table. The total height of the graph is equal to the Total counter in that section. This represents the total RAM usable by the operating system, and does
not include BIOS shadow pages, device memory, and so on.
该条柱形图的行高显示windows使用的物理内存情况(亮绿色区域,该区域没有相应的性能计数器)。该图中剩余的高度(暗绿色区域)相当于“物理内存(MB)”栏位中的“可用”计数器,后续的表格会讲到。该图的总高度相当于栏位中的“总数”计数器;总数表示操作系统能够使用的物理内存总量,并且不包含BIOS shadow pages(直译为BIOS影子页面,也就是将一些外围硬件设备自带的 BIOS ROM 映射到系统内存)与设备内存等(将一些外围硬件设备自带的存储器或缓存映射到系统内存)。
Physical Memory (MB): Total
物理内存(以MB,百万字节为单位):总数
Physical memory usable by Windows
即windows可用的物理内存,如前所述,等于内存条形图的总高;
Physical Memory (MB): Cached
已缓存
Sum of the following performance counters in the Memory object:
Cache Bytes, Modified Page List Bytes, Standby Cache Core Bytes,
Standby Cache Normal Priority Bytes, and Standby Cache Reserve Bytes (all in Memory object)
内存对象中的一些性能计数器总合,包括Cache Bytes,Modified Page List Bytes,Standby Cache Core Bytes,Standby Cache Normal Priority Bytes,以及 Standby Cache Reserve Bytes(译注:这里保持原文,避免翻译引起的语义准确性争议)
Physical Memory (MB):Available
可用
Amount of memory that is immediately available for use by the operating system, processes, and drivers. Equal to the combined size of the standby, free, and zero page lists.
To see the specific usage of paged and nonpaged pool, use the Poolmon utility, described in the “Monitoring Pool Usage” section.
使用在“监控页面池使用率”小节中讨论的工具Poolmon,可以查看分页池和非分页池的具体使用情况。
The Process Explorer tool from Windows Sysinternals (http://www.microsoft.com/technet/sysinternals) can show considerably more data about physical and virtual memory. On its main screen, click View and then System Information, and then choose the Memory tab. Here is an example display from a 32-bit Windows system:
We will explain most of these additional counters in the relevant sections later in this chapter.
Two other Sysinternals tools show extended memory information:
■ VMMap shows the usage of virtual memory within a process to an extremely fine level of detail.
■ RAMMap shows detailed physical memory usage.
These tools will be featured in experiments found later in this chapter.
Finally, the !vm command in the kernel debugger shows the basic memory management information available through the memory-related performance counters. This command can be useful if you're looking at a crash dump or hung system. Here's an example of its output from a 4-GB Windows client system:
We will describe many of the details of the output of this command later in this chapter.
我们将在本章稍后描述该命令输出的众多细节。
Services Provided by the Memory Manager
The memory manager provides a set of system services to allocate and free virtual memory, share memory between processes, map files into memory, flush virtual pages to disk, retrieve information about a range of virtual pages, change the protection of virtual pages, and lock the virtual pages into memory.
Like other Windows executive services, the memory management services allow their caller to supply a process handle indicating the particular process whose virtual memory is to be manipulated.
The caller can thus manipulate either its own memory or (with the proper permissions) the memory of another process. For example, if a process creates a child process, by default it has the right to manipulate the child process’s virtual memory. Thereafter, the parent process can allocate, deallocate, read, and write memory on behalf of the child process by calling virtual memory services and passing a handle to the child process as an argument. This feature is used by subsystems to manage the memory of their client processes. It is also essential for implementing debuggers because debuggers must be able to read and write to the memory of the process being debugged.
Most of these services are exposed through the Windows API. The Windows API has three groups of functions for managing memory in applications: heap functions (Heapxxx and the older interfaces Localxxx and Globalxxx, which internally make use of the Heapxxx APIs), which may be used for allocations
smaller than a page; virtual memory functions, which operate with page granularity (Virtualxxx); and memory mapped file functions (CreateFileMapping, CreateFileMappingNuma, MapViewOfFile, MapViewOfFileEx, and MapViewOfFileExNuma). (We’ll describe the heap manager later in this
chapter.)
The memory manager also provides a number of services (such as allocating and deallocating physical memory and locking pages in physical memory for direct memory access [DMA] transfers) to other kernel-mode components inside the executive as well as to device drivers. These functions begin with the prefix Mm. In addition, though not strictly part of the memory manager, some executive
support routines that begin with Ex are used to allocate and deallocate from the system heaps (paged and nonpaged pool) as well as to manipulate look-aside lists. We’ll touch on these topics later in this chapter in the section “Kernel-Mode Heaps (System Memory Pools).”
Large and Small Pages
The virtual address space is divided into units called pages. That is because the hardware memory management unit translates virtual to physical addresses at the granularity of a page. Hence, a page is the smallest unit of protection at the hardware level. (The various page protection options are described in the section “Protecting Memory” later in the chapter.) The processors on which Windows runs support two page sizes, called small and large. The actual sizes vary based on the processor
architecture, and they are listed in Table 10-1.
Note IA64 processors support a variety of dynamically configurable page sizes, from 4 KB up to 256 MB. Windows on Itanium uses 8 KB and 16 MB for small and large pages, respectively, as a result of performance tests that confirmed these values as optimal. Additionally, recent x64 processors support a size of 1 GB for large pages, but Windows does not use this feature.
The primary advantage of large pages is speed of address translation for references to other data within the large page. This advantage exists because the first reference to any byte within a large page will cause the hardware’s translation look-aside buffer (TLB, described in a later section) to have in its cache the information necessary to translate references to any other byte within the large page.
If small pages are used, more TLB entries are needed for the same range of virtual addresses, thus increasing recycling of entries as new virtual addresses require translation. This, in turn, means having to go back to the page table structures when references are made to virtual addresses outside the scope of a small page whose translation has been cached. The TLB is a very small cache, and thus large pages make better use of this limited resource.
To take advantage of large pages on systems with more than 2 GB of RAM, Windows maps with large pages the core operating system images (Ntoskrnl.exe and Hal.dll) as well as core operating system data (such as the initial part of nonpaged pool and the data structures that describe the state of each physical memory page). Windows also automatically maps I/O space requests (calls by
device drivers to MmMapIoSpace) with large pages if the request is of satisfactory large page length and alignment. In addition, Windows allows applications to map their images, private memory, and page-file-backed sections with large pages. (See the MEM_LARGE_PAGE flag on the VirtualAlloc, VirtualAllocEx, and VirtualAllocExNuma functions.) You can also specify other device drivers to be mapped with large pages by adding a multistring registry value to HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\LargePageDrivers and specifying the names of the
drivers as separately null-terminated strings.
Attempts to allocate large pages may fail after the operating system has been running for an extended period, because the physical memory for each large page must occupy a significant number (see Table 10-1) of physically contiguous small pages, and this extent of physical pages must furthermore
begin on a large page boundary. (For example, physical pages 0 through 511 could be used as a large page on an x64 system, as could physical pages 512 through 1,023, but pages 10 through 521 could not.) Free physical memory does become fragmented as the system runs. This is not a problem for allocations using small pages but can cause large page allocations to fail.
It is not possible to specify anything but read/write access to large pages. The memory is also always nonpageable, because the page file system does not support large pages. And, because the memory is nonpageable, it is not considered part of the process working set (described later). Nor are large page allocations subject to job-wide limits on virtual memory usage.
除了对于大页面的读/写访问外,无法指定其它操作。大页面内存也总是不可分页的,因为分页文件系统不支持大页面。这使得它不被认为是进程工作集的一部分(稍后解释),因而在进程虚拟内存使用方面,也没有大页面分配问题导致的工作范围限制。(译注:原文为 Nor are large page allocations subject to job-wide limits on virtual memory usage,如有更准确的译法请提出)
There is an unfortunate side effect of large pages. Each page (whether large or small) must be
mapped with a single protection that applies to the entire page (because hardware memory protection is on a per-page basis). If a large page contains, for example, both read-only code and read/write data, the page must be marked as read/write, which means that the code will be writable. This means that device drivers or other kernel-mode code could, as a result of a bug, modify what is supposed to be read-only operating system or driver code without causing a memory access violation.
If small pages are used to map the operating system’s kernel-mode code, the read-only portions of Ntoskrnl.exe and Hal.dll can be mapped as read-only pages. Using small pages does reduce efficiency of address translation, but if a device driver (or other kernel-mode code) attempts to modify a readonly part of the operating system, the system will crash immediately with the exception information pointing at the offending instruction in the driver. If the write was allowed to occur, the system would likely crash later (in a harder-to-diagnose way) when some other component tried to use the corrupted data.
If you suspect you are experiencing kernel code corruptions, enable Driver Verifier (described later in this chapter), which will disable the use of large pages.
Reserving and Committing Pages
Pages in a process virtual address space are free, reserved, committed, or shareable. Committed and shareable pages are pages that, when accessed, ultimately translate to valid pages in physical memory.
Committed pages are also referred to as private pages. This reflects the fact that committed pages cannot be shared with other processes, whereas shareable pages can be (but, of course, might be in use by only one process).
Private pages are allocated through the Windows VirtualAlloc, VirtualAllocEx, and VirtualAllocExNuma functions. These functions allow a thread to reserve address space and then commit portions of the reserved space. The intermediate “reserved” state allows the thread to set aside a range of contiguous virtual addresses for possible future use (such as an array), while consuming negligible system resources, and then commit portions of the reserved space as needed as the application runs. Or, if the size requirements are known in advance, a thread can reserve and commit in the same function call. In either case, the resulting committed pages can then be accessed by the thread. Attempting to access free or reserved memory results in an exception because the page isn’t mapped to any storage that can resolve the reference.
私有页面是通过Windows函数VirtualAlloc, VirtualAllocEx, 以及 VirtualAllocExNuma分配的。这些函数允许一个线程预留出地址空间,然后提交部分的预留空间(作为私有页面使用)。这中间的“预留”状态允许该线程留出一系列连续相邻的虚拟地址,以备将来使用(例如数组),同时消耗的系统资源可以忽略不计,然后根据应用程序运行时的需求,提交部分的预留空间使用。或者,如果事先知道要求分配的大小,线程可以在相同的函数调用中申请预留并提交使用。不论哪种情况,由此产生的提交页面稍后可被该线程访问。试图访问空闲的(free)和保留的(reserved)内存会导致一个异常,因为这些虚拟页面没有映射到任何能够解析该引用的存储器位置。(译注:此句经过自行润色,原文为“because the page isn't mapped to any storage that can resolve the reference.”)
If committed (private) pages have never been accessed before, they are created at the time of first access as zero-initialized pages (or demand zero). Private committed pages may later be automatically written to the paging file by the operating system if required by demand for physical memory.
“Private” refers to the fact that these pages are normally inaccessible to any other process.
Note There are functions, such as
ReadProcessMemory and WriteProcessMemory, that apparently permit cross-process memory access, but these are implemented by running kernel-mode code in the context of the target process (this is referred to as attaching to the process). They also require that either the security descriptor of the target process grant the accessor the PROCESS_VM_READ or PROCESS_VM_WRITE right, respectively, or that
the accessor holds SeDebugPrivilege, which is by default granted only to members of the Administrators group.
Shared pages are usually mapped to a view of a section, which in turn is part or all of a file, but may instead represent a portion of page file space. All shared pages can potentially be shared with other processes. Sections are exposed in the Windows API as file mapping objects.
When a shared page is first accessed by any process, it will be read in from the associated mapped file (unless the section is associated with the paging file, in which case it is created as a zero-initialized page). Later, if it is still resident in physical memory, the second and subsequent processes accessing it can simply use the same page contents that are already in memory. Shared pages might also have been prefetched by the system.
共享页面通常映射到“一节”视图,该节又是一个磁盘文件的一部分或者全部,而不是代表磁盘分页文件的一部分。(译注:这句行文非常怪异,原文为“Shared pages are usually mapped to a view of a section, which in turn is part or all of a file, but may instead represent a portion of page file space”)。所有共享页面都有可能被其它进程共享。其中一部分共享页面通过Windows API,作为“文件映射对象“对外暴露。
当一个共享的页面首次被任何进程访问时,将从(磁盘上)关联的映射文件读入内存(直到该部分与页面文件关联,在此情况下,它被作为一个初始化为零的页面[zero-initialized page]创建)。
随后,如果此共享页面仍旧驻留在物理内存中,第二个以及后续的进程访问时,可以简单地使用已经在内存中的页面内容(与磁盘上的相同)。共享的页面也可能已经被系统预取(prefetched)进内存,甚至不需要等待进程首次访问才读入。
Two upcoming sections of this chapter, “Shared Memory and Mapped Files” and “Section Objects,” go into much more detail about shared pages. Pages are written to disk through a mechanism called modified page writing. This occurs as pages are moved from a process’s working set to a systemwide list called the modified page list; from there, they are written to disk (or remote storage). (Working
sets and the modified list are explained later in this chapter.) Mapped file pages can also be written back to their original files on disk as a result of an explicit call to FlushViewOfFile or by the mapped page writer as memory demands dictate.
You can decommit private pages and/or release address space with the VirtualFree or VirtualFreeEx function. The difference between decommittal and release is similar to the difference between reservation and committal—decommitted memory is still reserved, but released memory has been freed;
it is neither committed nor reserved.