分页与非分页内存

在写驱动的时候,经常要调用ExAllocatePoolWithTag函数分配内存,其中第一个参数可以是如下几个:

 

 

NonPagedPool从非分页内存池中分配内存
PagedPool从分页内存池中分配内存
NonPagedPoolMustSucceed从非分页内存池中分配内存,如果不能分配则产生bugcheck
NonPagedPoolCacheAligned从非分页内存池中分配内存,并确保内存与CPU cache对齐
NonPagedPoolCacheAlignedMustS与NonPagedPoolCacheAligned类似,但如果不能分配则产生bugcheck
PagedPoolCacheAligned

从分页内存池中分配内存,并确保内存与CPU cache对齐

 

 

其中,主要的两个区别就是分页内存和非分页内存。

分页内存是低中断级别的例程可以访问的。

而非分页内存则是各个中断级别的例程都可以使用的。

区别在于:
分页内存是虚拟内存,在物理上未必总是能得到。

操作系统实现虚拟内存的主要方法就是通过分页机制。在Win32中,物理地址空间,二维虚拟地址空间和实际内存地址是三个不同的概念。操作系统通过段选择子构成二维虚拟地址空间,每个进程有一个4G的地址空间,然后操作系统的内存管理器件把每个进程映射到一维物理地址空间的不同部分,但是因为我们实际机器上大都没有4G内存,所以,实际内存空间是物理地址空间的子集。

分页管理器把地址空间划分成4K大小的页面(非Intel X86体系与之不同),当进程访问某个页面时,操作系统首先在Cache中查找页面,如果该页面不在内存中,则产生一个缺页中断(Page Fault),进程就会被阻塞,直至要访问的页面从外存调入内存中。
我们知道,在处理低优先级的中断时,仍可以发生高优先级的中断。既然缺页过程也是一个中断过程,那么就产生一个问题,即,缺页中断和其他中断的优先级的问题。如果在高于缺页中断的中断优先级上再发生缺页中断,内核就会崩溃。所以在DISPATCH_LEVEL级别以上,绝对不能使用分页内存,一旦使用分页内存,就有发生缺页中断的可能,前面说过,这样会导致内核崩溃。

<think>我们正在讨论Windows内存管理中的分页内存非分页内存。根据引用[1][3],我们可以知道: - 分页内存(Paged Memory)是指可以被交换到磁盘上的内存页,当物理内存不足时,操作系统可以将这些页换出到磁盘,需要时再换入。 - 非分页内存(NonPaged Memory)则是必须常驻在物理内存中的内存页,不能被交换到磁盘。 引用[3]还提到了在DDK(Driver Development Kit)中如何通过代码段数据段的编译指令来指定代码或数据是分页还是非分页的。 现在,我们需要详细解释两者的区别,包括它们的定义、使用场景、访问限制等。 结合IRQL的知识(用户之前的问题),我们知道在IRQL >= DISPATCH_LEVEL(即2)时,不能访问分页内存,因为此时系统无法处理缺页中断(page fault),所以必须使用非分页内存。 因此,我们可以这样组织回答: 1. 定义分页内存非分页内存。 2. 解释为什么需要非分页内存(主要是在高IRQL下不能处理缺页中断)。 3. 说明在驱动开发中如何指定代码或数据为非分页(使用DDK提供的宏)。 4. 使用场景:分页内存用于一般情况,非分页内存用于中断处理、DPC等运行在高IRQL的代码或数据。 5. 性能影响:非分页内存会减少可用物理内存,因此应谨慎使用。 另外,引用[2]提到了分段分页,但我们的问题聚焦在分页非分页内存,所以可以略过分段的内容。 我们还需要注意,在回答中要自然地添加引用标识,如[^1][^3]等。 最后,生成相关问题。 下面开始回答:</think>### Windows内存管理中分页内存非分页内存的区别 #### 1. **核心定义** - **分页内存 (Paged Memory)** 可被交换到磁盘的虚拟内存区域。当物理内存不足时,操作系统会将这部分内存内容暂存至硬盘的页面文件(Pagefile.sys),需要时再加载回内存[^1][^3]。 **特点**: - 允许访问时触发缺页异常(Page Fault) - 仅能在 IRQL < `DISPATCH_LEVEL`(即0或1)时访问 - 通过 `PAGED_CODE()` 宏或 `#pragma alloc_text(PAGE, ...)` 指定 - **非分页内存 (NonPaged Memory)** 必须常驻物理内存的区域,不能被交换到磁盘[^1][^3]。 **特点**: - 禁止触发缺页异常 - 可在任意 IRQL(包括 `DISPATCH_LEVEL` 及以上)访问 - 通过 `NonPagedPool` 分配或 `#pragma alloc_text(INIT, ...)` 指定 #### 2. **技术原理对比** | **特性** | **分页内存** | **非分页内存** | |------------------------|----------------------------------|--------------------------------| | **交换机制** | 可交换到磁盘 | 永久驻留物理内存 | | **缺页异常处理** | 允许触发 | 禁止触发 | | **IRQL 访问限制** | 仅限 IRQL < 2 | 任意 IRQL (0~31) | | **内存分配函数** | `ExAllocatePoolWithTag(PagedPool)` | `ExAllocatePoolWithTag(NonPagedPool)` | | **典型应用场景** | 用户态程序、低IRQL驱动代码 | 中断处理、DPC、自旋锁临界区 | #### 3. **访问限制的本质** 在 IRQL ≥ `DISPATCH_LEVEL` 时(如硬件中断处理中): - **分页内存访问风险**: 若触发缺页异常,系统需执行磁盘I/O加载页面,但高IRQL下线程调度被禁用,无法等待I/O完成,导致系统崩溃(蓝屏错误 `IRQL_NOT_LESS_OR_EQUAL`)[^1]。 - **非分页内存安全性**: 物理地址始终有效,无需页面加载,避免上述问题。 #### 4. **开发实践示例 **驱动代码中的显式声明: ```c // 声明非分页内存中的函数(可在高IRQL运行) #pragma alloc_text(INIT, DriverHighIrqlRoutine) // 声明分页内存中的函数(仅低IRQL运行) #pragma alloc_text(PAGE, DriverLowIrqlRoutine) // 分配非分页内存(中断处理中使用) PVOID buffer = ExAllocatePool2(NonPagedPool, size, 'TAG'); ``` #### 5. **典型应用场景** - **分页内存适用**: - 文件系统缓存 - 用户态进程内存 - 驱动中不涉及中断的常规逻辑 - **非分页内存必需**: - 中断服务例程 (ISR) - 延迟过程调用 (DPC) - 自旋锁保护的临界区 - 设备DMA缓冲区 > **关键设计原则**:非分页内存占用应最小化,因其减少可用物理内存,过度使用会导致系统频繁换页,降低性能[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值