内存管理(1)概述&系统空间初始化

         大概看了些内存管理的东西,整理一下笔记,陆续贴上来。

参考《Windows Internals》、《Windows内核原理与实现》、WRK。调试环境WRK x86,非PAE。
开始时比较乱,因为还没想好要如何排版 ,不过反正开头都是些基础东西,匆匆带过好了

一、概述,内存管理一些基础

主要要实现的功能:

1.    进程间内存实现隔离
2.内存的申请和释放
3.  主存和辅存页面的换入和换出(包括页面映射文件)

大致分为用户模式空间管理,系统空间管理,还有物理内存的管理

页式内存管理基础(实现功能1):
虚拟地址对物理地址的转换,实现进程间内存的隔离。

虚拟地址的意义:


查询物理页面的过程



多层查表效率受到影响,CPU有自己的缓存:TLB

PDE&PTE 的意义



工作集:
进程当前正在使用的物理页面的集合。如果页面未被访问,却在工作集中,不会被换出

WIN内存管理概述:
★ 段式管理被屏蔽,CS SS DS ES 在GDT中所对应的段基地址都是0,段最大偏移是0xffff000

★    进程的虚拟地址分配情况 用VAD描述
★    物理内存页面状态 PFN库来描述
★    相同类型的页面用链表连接
★    使用异常来处理换页
★    工作及管理器 对进程的工作集加以修剪
主要组件:
执行体层面 提供内存管理的服务(也包括底层的支持)
异常处理 换页
系统线程 平衡集管理器 1s一次 全局管理
进程栈交换器 线程切换时,如果一个进程无active thread时,进程的内存页可被换出(换出的是进程的4个最基本页面…)
0页面线程 负责内存0化
修改页面写出器 

===============================================================

二、系统对内存空间的初始化(出现大量名词...但只是简要流程,细节要看过管理算法再讨论~):


BOOLEAN
MmInitSystem (
IN ULONG Phase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)

/*++

Routine Description:

This function is called during Phase 0, phase 1 and at the end 
of phase 1 ("phase 2") initialization.

Phase 0 initializes the memory management paging functions, 初始化内存管理换页函数,内存池,PFN数据库
nonpaged and paged pool, the PFN database, etc.

Phase 1 initializes the section objects, the physical memory   初始化section对象 物理内存对象 开启内存管理的系统线程
object, and starts the memory management system threads.

Phase 2 frees memory used by the OsLoader.  释放内存

MmInitSystem在执行体初始化函数ExpInitializeExecutive 中调用,

0阶段:

1 初始化了临时事件

KeInitializeEvent (&MiTempEvent, NotificationEvent, FALSE); 

MiLowMemoryEvent = &MiTempEvent;
MiHighMemoryEvent = &MiTempEvent;

MiLowPagedPoolEvent = &MiTempEvent;
MiHighPagedPoolEvent = &MiTempEvent;

MiLowNonPagedPoolEvent = &MiTempEvent;
MiHighNonPagedPoolEvent = &MiTempEvent;

2 0阶段中划分了系统内存空间,一些全局变量被设置,比如
MmHighestUserAddress = (PVOID)(KSEG0_BASE - 0x10000 - 1);
MmUserProbeAddress = KSEG0_BASE - 0x10000;
MmSystemRangeStart = (PVOID)KSEG0_BASE;

还有页目录,系统映像大小等等一系列全局变量。整体划分情况




其中Session space又按照 会话内存池(16M,属于会话空间的换页内存池) 会话视图(20M) SESSION WS 会话映像文件(win32k 视频驱动 打印驱动的映像文件) 的顺序排列


MiInitMachineDependent (LoaderBlock);

MmPhysicalMemoryBlock = MmInitializeMemoryLimits (LoaderBlock,
IncludeType,
NULL);

3 建立页目录 页表 初始化非换页内存池 等实质性的工作MiInitMachineDependent 真正实现虚拟内存的机制


MiInitMachineDependent:
设置当前进程的页目录

PointerPte = MiGetPdeAddress (PDE_BASE);
PdePageNumber = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);

CurrentProcess = PsGetCurrentProcess ();

DirBase = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) << PAGE_SHIFT;

CurrentProcess->Pcb.DirectoryTableBase[0] = DirBase;

//
// Unmap the low 2Gb of memory.
//

PointerPde = MiGetPdeAddress (0);
LastPte = MiGetPdeAddress (KSEG0_BASE);

MiZeroMemoryPte (PointerPde, LastPte - PointerPde);  清空了0~2GB的目录 这是空闲进程,没有用户空间

接下来的大段代码就是计算Pfn数据库和非换页内存池得大小,然后开始分配系统PTE和扩展的非换页内存池的页表

StartPde = MiGetPdeAddress (MmNonPagedSystemStart);        获得开始和结束的目录项
EndPde = MiGetPdeAddress ((PVOID)((PCHAR)MmNonPagedPoolEnd - 1));

while (StartPde <= EndPde) {

ASSERT (StartPde->u.Hard.Valid == 0);

//
// Map in a page table page, using the
// slush descriptor if one exists.
//

TempPde.u.Hard.PageFrameNumber = MxGetNextPage (1, TRUE);
*StartPde = TempPde;            赋值一个分配好的目录项,申请了物理内存,需要对其进行清零,但现在没有建立起页表的映射,如何反查页目录的虚拟内存地址?

PointerPte = MiGetVirtualAddressMappedByPte (StartPde);
左移10位,这个操作基于页目录的自映射方案,在页目录访问自己时,0xc0000000的虚拟地址对应查表PDE_BASE+0xc00,也就是0xc00指向的是0xc0000000的地址 这下0xc0000000便作为PTE 二次查表 关于自映射方案 可以阅读
http://hi.baidu.com/wzt85/blog/item/a28aec0f01c7dc276159f377.html 作者 wzt85
RtlZeroMemory (PointerPte, PAGE_SIZE);
StartPde += 1;


接下来分配PFN数据库和非换页内存池了

MmPfnDatabase 是MMPFN的数组,记录了物理页面的状态

MmFreePagesByColor  初始化
MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors];

for (i = 0; i < MmSecondaryColors; i += 1) {
MmFreePagesByColor[ZeroedPageList][i].Flink = MM_EMPTY_LIST;
MmFreePagesByColor[ZeroedPageList][i].Blink = (PVOID) MM_EMPTY_LIST;
MmFreePagesByColor[ZeroedPageList][i].Count = 0;
MmFreePagesByColor[FreePageList][i].Flink = MM_EMPTY_LIST;
MmFreePagesByColor[FreePageList][i].Blink = (PVOID) MM_EMPTY_LIST;
MmFreePagesByColor[FreePageList][i].Count = 0;
}

PFN数据库与物理页面实际状态同步

初始化非换页内存池,系统PTE池

最后针对本进程建立起一些列相关的内容,以及工作及链表,建立PDE映射超空间,进程的VAD等等内容,等到后面再细看了

4. MmInitializeMemoryLimits 获取物理内存信息,并且申请一个位图来记录物理页面是否有效


Bitmap = ExAllocatePoolWithTag (
NonPagedPool,
(((MmHighestPossiblePhysicalPage + 1) + 31) / 32) * 4,
'  mM');

if (Bitmap == NULL) {
KeBugCheckEx (INSTALL_MORE_MEMORY,
MmNumberOfPhysicalPages,
MmLowestPhysicalPage,
MmHighestPhysicalPage,
0x101);
}

5. MiReloadBootLoadedDrivers (LoaderBlock); ntldr把启动驱动放在了80000000处,现在可以开始重定位到系统pte处了

6.确定系统内存规模,建立系统缓存和系统缓存工作集

7 MiBuildPagedPool ();建立换页池

至此系统空间的定义和初始化都已经完成了,初始化了一下PsLoadedModuleList,由MiInitializeLoadedModuleList实现

1阶段:
主要工作:创建\\Device\\PhsicalMemory的内存区对象,设置MmSharedUserDataPte 使得0xffdf0000和0x7ffe0000共享内存

初始化会话空间

开启修改页面写出器

初始化内存事件

开启平衡及管理器KeBalanceSetManager KeSwapProcessOrStack两个线程

开启零化内存线程

对加载模块设置保护属性
2阶段:
设置加载模块PAGE段为可换页的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值