非页面内存泄漏

非页面缓冲池,是一种包含各种系统虚拟地址范围的内存池,从任何地址空间均可进行访问。

非页面缓冲池

这是一个包含各种系统虚拟地址范围的内存池,这些地址范围可以保证始终驻留在物理内存中,因此从任何地址空间均可进行访问,而不会产生页面输入/输出 (I/O)。非页面缓冲池在系统初始化期间创建,内核模式组件用它来分配系统内存

在写驱动的时候,经常要调用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级别以上,绝对不能使用分页内存,一旦使用分页内存,就有发生缺页中断的可能,前面说过,这样会导致内核崩溃。

另一种解释:

虽然可以寻址4GB的内存,而在PC里往往没有如此多的真实物理内存。操作系统和硬件(这里指的是CPU中的内存管理单元MMU)为使用者提供了虚拟内存的概念。Windows的所有程序(包括Ring0层和Ring3层的程序)可以操作的都是虚拟内存。之所以称为虚拟内存,是因为对它的所有操作,最终会变成一系列对真实物理内存的操作。在CPU中有一个重要的寄存器CR0,它是32位的寄存器,其中的一个位(PG位)是负责告诉系统是否分页的。Windows在启动前会将它的PG位置1,即允许分页。宏PAGE_SIZE记录分页大小4KB,4GB的虚拟内存会被分割成1M个分页单元。

         有一部分单元会和物理内存对应起来,这种对应不是一一对应,而是多对一的映射,多个虚拟内存页可以映射同一个物理内存页。还有一部分单元会被映射成磁盘上的文件,并标记为脏的(Dirty)。0~0X7FFFFFFF范围内的虚拟内存,即低于2GB的虚拟地址为用户内核模式地址,而0X80000000~0XFFFFFFFF范围内的虚拟内存,即高2GB的虚拟内存,为内核模式地址。Windows的核心代码和Windows的驱动程序加载的位置都是在高2GB的内核地址里,所以一般的应用程序是不能访问到这些核心代码和重要数据的。同时Windows操作系统在进程切换时,保持内核模式地址是完全相同的。也就是说,所有进程的内核地址映射完全一致,进程切换的时候,只改变用户模式地址的映射。

      Windows规定有些虚拟内存页面是可以交换到文件中的,这类内存被称为分页内存。而有些虚拟内存永远不会交换到文件中,这些内存被称为非分页内存。当程序的中断请求级在DISPATCH_LEVEL之上(包括DISPATCH_LEVEL层),程序只能使用非分页内存,否则将导致蓝屏死机。

操作系统为windows server 2012 R2 Standard

系统状态:
 




应用程序所占用内存:

 




poolmon的状态(按照NonPage的占用从大到小排列了):

 




非页面缓冲池那儿(Pool N) 的值为60G左右,但是看列表里面,最大的才426M。页面缓冲池也没问题。

系统跑着我们的c++应用程序,就是用new申请内存,不可能触到非页面缓冲池这块。但是调用了海康大华的sdk连接镜头。现在会这样一直涨直到内存耗尽,需要重启机器才能解决。如果是sdk的问题,我应该怎么调试找出证据,因为看自己exe相关内存都是正常的。

非页面缓冲池并非突然涨,而是无规律的慢慢涨,机器运行了1个月左右,
问:
现在不知道该怎么调试。各位大佬有没有办法怎么看谁在吃非页面缓冲池的内存?

答:

非分页内存增加,而不是应用层内存增加,则很可能是sdk有内核层的代码出现内存泄露,而调试方法你大可以用windbg来双机调试,当然,不应当在生产机器上,可以在虚拟机中同样执行这些程序,通过windbg来详细调试的
只要看不到应用层的内存增加,那么可能就需要windbg来进入内核调试了,可以查看vmware双机调试
内存泄露,当然不会一下子增加上来,不过在你看到一个程序内存不做事一直增加,那就可能是泄露了
事实上,如果不是你自己代码在内核层,即便调试到内核的内存泄露,也无意义啊

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值