windows内存管理(124)

一个进程是4gb虚拟内存(win32),存在分区,一般用户分区为2gb。

虚拟内存,也只是个内存对应表而已。实际内存,物理内存地址

vitrualalloc先向这么多虚拟内存预定一块内存,再分配物理存储器,再使用。

原话:最好把物理存储器看成是保存在磁盘(通常是硬盘)上页交换文件中的数据。

.exe或者dll(以下的说法dll没测试过)文件,文件头有相应的数据,通过那个,知道代码和数据大小等。然后就预定相应大小的内存空间,硬盘的话就直接映射内存文件上去,软盘就复制上去。

分页内存和非分页内存

首先介绍几个术语:

进程上下文,就是表示进程信息的一系列东西,包括各种变量、寄存器以及进程的运行的环境。这样,当进程被切换后,下次再切换回来继续执行,能够知道原来的状态。
中断上下文,就是中断发生时,原来的进程执行被打断,那么就要把原来的那些变量保存下来,以便中断完成后再恢复。

Windows NT和Windows 98都是运行在支持虚拟地址空间的计算机上,虚拟地址空间或者映射到一段真实的物理内存,或者映射到交换文件中的页帧。

每一个进程有4G的虚拟地址空间空间(因为一般机器是32位),这4G的空间被分为用户模式地址空间以及用户模式地址空间。无论何时我们需要访问计算机内存,都要使用内核模式的虚拟地址。每一个用户模式进程都有自己的地址上下文,记录了进程信息的一系列东西。当Windows NT调度器把控制从一个进程的当前线程切换到另一个进程的某个线程时,与进程相对应的虚拟地址空间也被更换(执行到别的进程了,也就是跑到另外的一个4G的地址)。线程切换的一个步骤就是改变处理器当前使用的页表,以便它能引用新线程的进程上下文。

虚拟内存系统的特征就是能使软件有一个比物理内存大得多的虚拟内存空间。为了做到这一点,内存管理器需要在物理内存和磁盘文件间交换页帧。但操作系统的某些部分是不能被分页的,这些内存用来支持内存管理器本身。最明显的例子就是,用于处理页故障的代码和数据结构必须常驻内存。

Windows NT把内核模式地址空间分成分页内存池和非分页内存池。(用户模式地址空间总是分页的) 必须驻留的代码和数据放在非分页池;不必常驻的代码和数据放在分页池中。Windows NT为决定代码和数据是否需要驻留非分页池提供了一个简单规则。

非分页内容的空间是很小的,所以一般的东西都会放入分页内存中。

执行在高于或等于DISPATCH_LEVEL级上的代码必须存在于非分页内存中。

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

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

最后我来说下驱动编程的的宏

PAGEDCODE
对于#pragram来说,code_seg是函数,data_seg是变量

LOCKEDCODE

INITCODE

首先,驱动函数是严格分了IRQL的。
运行一个函数,如fun,如果永远是在DISPATCH_LEVEL上运行。

就最好用非分页内存LOCKEDCODE进行开辟函数
在函数中对内存的开辟也必须是ExAllocatePool NonPagePool类型的


如果对于在这种irql的运行函数进行PAGEDCODE声明和ExAllocatePool PagePool


当出现蓝屏:而如果访问分页内存的话,(注意,这是关键)如果分页内存数据不在物理内存中,也就是被交换到了虚拟内存页面文件中,将触发内存缺页中断,windows将会试图访问虚拟内存页面文件pagefile.sys,把被交换出的数据读入物理内存中,可是,访问文件是会引发i/o操作的,i/o操作中会有等待,
接着,系统直接崩溃

没有蓝屏:
就算你的页面属性是分页内存,但是没有被交换出去,还是在内存中,访问时不会引发缺页中断
但是,哪天,windows发现内存不够了,把你的代码数据交换到内存页面文件中(pagefile。sys),
呵呵,立即蓝屏~~~

所以建议严格分内存声明。。。。

// //