任务管理器里的页面错误(PageFault)

Windows任务管理器里的页面错误(Pagefault)一般是指发生缺页中断的计数。

什么叫缺页中断呢?

这其实是与操作系统的设计有关。比如我们常说的windows操作系统,32位的进程一般总共有4G的虚拟内存,高2G用于与其与进程的共享,即内核内存,低2G为该进程的私有占用。这样所以每一个单独的进程会至步占用2G的私有虚拟内存。但我们运行的机器通常有少则几十多则一两百的进程个数,这样算下来,所有的进程至少需要两百至四百多的虚拟内存,但我们的电脑配置一般的DDR也的8G或者16G,相比几百G的内存远远不够,那怎么办呢?
其实是这样的,操作系统对进程的内存分配是按需分配,即真实使用的才进行真正的物理内存分配,否则只是进行一个内存占用的标记,不会分配具体的物理内存。但即是这样做,物理内存也不够,怎么办呢,这时就引出了另一个东西叫做缺页中断。

什么是缺页中断?

缺页中断就是当应用程序试图申请内存(此处仅限大块内存,不考虑malloc等小块申请)的时候,一般先是向操作系统申请一段虚拟地址范围,OS将这段内存地址范围标为有效,但并不实际分配内存,需要等待应用程序真正使用到这段内存时,才尝试真正分配内存。当程序真正尝试用这段内存的时候,就会触发缺页中断,CPU告诉操作系统,有个任务要用这块内存了,赶快准备一下。

缺页中断是怎么操作的呢?

申请地址范围->标记地址可用->等待内存被使用(缺页中断)->处理缺页中断,把一段真正的物理内存映射到这块地址上。
这块真正的物理内存映射执行的就是从物理内存中找到没有用的物理内存页进行虚拟内存(线性地址)到物理内存的映射,当然如果一块内存有时虽然有数数了,但操作系统发现它又很常时间又不读写,系统又会自动将其写内存磁上的虚拟内存,写入的这个东西一般就是我们C盘上看到的叫”pagefile.sys”的分页文件。

题外话

有开发过windows驱动的朋友,肯定会有过这样的经历。在申请内存时,会常用函数ExAllocatePoolWithTag,它的第一个参数POOL_TYPE就是指定内存的类型的。

PVOID 
  ExAllocatePoolWithTag(
    IN POOL_TYPE  PoolType,
    IN SIZE_T  NumberOfBytes,
    IN ULONG  Tag
    );

这里我们引用WDK关于POOL_TYPE的介绍:
POOL_TYPE的类型

typedef enum _POOL_TYPE {
  NonPagedPool,
  PagedPool,
  NonPagedPoolMustSucceed,
  DontUseThisType,
  NonPagedPoolCacheAligned,
  PagedPoolCacheAligned,
  NonPagedPoolCacheAlignedMustS
} POOL_TYPE;

其中常用的2个NonPagedPool和PagedPool
NonPagedPool

Nonpaged pool, which is nonpageable system memory. Nonpaged pool can be accessed from any IRQL, but it is a scarce resource and drivers should allocate it only when necessary.
The system can allocate buffers larger than PAGE_SIZE from nonpaged pool only in multiples of PAGE_SIZE. Requests for buffers larger than PAGE_SIZE, but not a PAGE_SIZE multiple, waste nonpageable memory.

PagedPool

Paged pool, which is pageable system memory. Paged pool can only be allocated and accessed at IRQL < DISPATCH_LEVEL.

其它相关参考:Windows内存类型介绍