首页
社区
课程
招聘
[原创]Windows内存管理机制之我见
发表于: 2013-3-14 17:17 7217

[原创]Windows内存管理机制之我见

2013-3-14 17:17
7217
[QUOTE][/QUOTE]
把笔记帖上来...整理一下..来加深理解...相互学习

本文以WRK1.2的代码为参考,主要分析管理器的工作流程来理解内存管理。   
内存管理是windows执行体的一部分,内存管理器的任务是:虚拟内存管理(把进程的虚拟地址空间映射到物理内存中;将物理内存的内容写入磁盘上)、一组核心服务(内存映射文件、写时复制内存以及为应用程序提供大的、稀疏的地址空间支持)。

    其中6个关键组件,分别运行于6个不同的内核模式系统线程环境中:
    工作集管理器(优先级16):平衡集管理器(内核创建的一个系统线程)每秒钟调用它一次,以及当空闲内存的数量降低到某个特定阈值以下时平衡集管理器也会调用它。

    工作集管理器驱动了总体内存管理策略,如工作集修剪、页面变老( aging)、以及修改页面的写出等。

     进程/栈交换器(优先级23):执行进程栈和内核线程栈的换入和换出操作。当需要执行换入(inswap)或换出(outswap)操作时,内核中的平衡集管理器和线程调度代码唤醒此线程。

    已修改页面写出器(优先级17):将已修改页面的列表上的脏页面写回到适当的页面文件中。当列表大小需要减小时,此线程被唤醒。

    映射页面写出器(优先级17):将映射文件中的脏页面写到磁盘上。当修改列表需要减小或映射文件的页面在修改列表上超过5分钟时,它被唤醒。这个页面写出器是必要的,因为可能会产生页面错误,这些页面错误又会导致请求空闲页面。如果没有空闲页面,而且只有一个已修改页面写出器线程。那么,系统可能会死锁,一直等待空闲页面。

    解引用段线程(dereference  segment  thread):(优先级18)负责页面缓存的减少,以及页面文件的增减(如,没有虚拟地址空间可用于换页池的增长,那么该线程修剪页面缓存,以便这些页面所在的换页池能腾出[释放]一部分供重新使用)。

    零页面线程(优先级0):将空闲列表上的页面清成零,从而有一个零页面缓存可用来满足将来“零页面错误”之需。(在有些情况下,内存零化是通过一个更快捷的函数 MiZeroInParallel 来完成的)

    在这六个组件中,工作集管理器较为重要(或应表达为跟其它几个组件比较有关系),例如已修改页面写出器(例程MiModifiedPageWriterWorker)需要等待工作集管理器设置事件对象MmModifiedPageWriterEvent

VOID
MiModifiedPageWriterWorker (
    VOID
    )
{
    PRTL_BITMAP Bitmap;
    KIRQL OldIrql;
    static KWAIT_BLOCK WaitBlockArray[ModifiedWriterMaximumObject];
    PVOID WaitObjects[ModifiedWriterMaximumObject];
    NTSTATUS WakeupStatus;
    LOGICAL MappedPage;
    PMMMOD_WRITER_MDL_ENTRY ModWriterEntry;

    PsGetCurrentThread()->MemoryMaker = 1;

    //
    // Wait for the modified page writer event or the mapped pages event.
    //

    WaitObjects[NormalCase] = (PVOID)&MmModifiedPageWriterEvent;
    WaitObjects[MappedPagesNeedWriting] = (PVOID)&MiMappedPagesTooOldEvent;

    for (;;) {

        WakeupStatus = KeWaitForMultipleObjects (ModifiedWriterMaximumObject,
                                                 [B]&WaitObjects[0],//等待事件对象MmModifiedPageWriterEvent[/B]
                                                 WaitAny,
                                                 WrFreePage,
                                                 KernelMode,
                                                 FALSE,
                                                 NULL,
                                                 &WaitBlockArray[0]);

        LOCK_PFN (OldIrql);

        for (;;) {
................


    工作集管理器是被平衡集管理器所调用,通过设置信号的方式来驱动整个内存管理策略,例如工作集修剪等。各个管理器具体负责的职责,上面已经列明,比较好理解,但是它们彼此之间的关系,特别是工作集管理器是如何被系统所驱动的?所以为了更好理解,接下来从内存管理的初始化开始分析:
内存管理的初始化例程是MmInitSystem,在 ntoskrnl的初始化工作的phase 0 和 phase 1被调用,它在WRK中是被遮掩描述的: 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,
    nonpaged and paged pool, the PFN database, etc.

    Phase 1 initializes the section objects, the physical memory
    object, and starts the memory management system threads.

    Phase 2 frees memory used by the OsLoader.
其中在phase 1的 时候创建启动了两个线程: KeBalanceSetManager(平衡集管理器)和 KeSwapProcessOrStack(交换管理器)代码如下
    //
        // Start the balance set manager.
        //
        // The balance set manager performs stack swapping and working
        // set management and requires two threads.
        //

        InitializeObjectAttributes (&ObjectAttributes, NULL, 0, NULL, NULL);

        if (!NT_SUCCESS(PsCreateSystemThread (&ThreadHandle,
                                              THREAD_ALL_ACCESS,
                                              &ObjectAttributes,
                                              0L,
                                              NULL,
                                              KeBalanceSetManager,
                                              NULL))) {

            return FALSE;
        }
        ZwClose (ThreadHandle);

        if (!NT_SUCCESS(PsCreateSystemThread (&ThreadHandle,
                                              THREAD_ALL_ACCESS,
                                              &ObjectAttributes,
                                              0L,
                                              NULL,
                                              KeSwapProcessOrStack,
                                              NULL))) {

            return FALSE;
        }
        ZwClose (ThreadHandle);


       KeBalanceSetManager:等待两个事件对象(其中一个有信号即可): MmWorkingSetManagerEvent  (a memory management memory low event, a swap event),  PeriodTimer  (the expiration of the period timeout rate that the balance set manager runs at.),然后调用MmWorkingSetManager完成 working set 的管理(分析、调整、修剪等)
VOID
KeBalanceSetManager (
    IN PVOID Context
    )
{
.........
    do {

 
        //等待事件信号
        Status = KeWaitForMultipleObjects(MaximumObject,
                                          &WaitObjects[0],
                                          WaitAny,
                                          Executive,
                                          KernelMode,
                                          FALSE,
                                          NULL,
                                          &WaitBlockArray[0]);

        //
        // Switch on the wait status.
        //

        switch (Status) {


        //定时器唤醒
        case TimerExpiration:

            //
            // Adjust I/O lookaside credits.
            //

#if !defined(NT_UP)

            KiAdjustIrpCredits();

#endif

            //
            // Adjust the depth of lookaside lists.
            //

            ExAdjustLookasideDepth();

            //
            // Execute the virtual memory working set manager.
            //

            [B]MmWorkingSetManager();//调用[/B]
            //
            // Attempt to initiate outswapping of kernel stacks.
            //
            // N.B. If outswapping is initiated, then the dispatcher
            //      lock is not released until the wait at the top
            //      of the loop is executed.
            //

            StackScanPeriod -= 1;//计数,
            if (StackScanPeriod == 0) {
                StackScanPeriod = StackScanTime;//一般是4(有一种情况是8),就是每第四次被1秒钟定时器唤醒时,才驱动交换管理器
                if (InterlockedCompareExchange(&KiStackOutSwapRequest,
                                               TRUE,
                                               FALSE) == FALSE) {

                    KiLockDispatcherDatabase(&OldIrql);
                    KiSetInternalEvent(&KiSwapEvent, KiSwappingThread);
                    Thread = KeGetCurrentThread();
                    Thread->WaitNext = TRUE;
                    Thread->WaitIrql = OldIrql;
                }
            }

            break;

         //低内存事件
        case WorkingSetManagerEvent:

            //
            // Call the working set manager to trim working sets.
            //

            [B]MmWorkingSetManager();//调用[/B]
            break;
..........
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
2
WRK的代码很漂亮~~
2013-3-14 18:42
0
雪    币: 228
活跃值: (115)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
3
好像引用WRK的代码超过最高限制....小心MS找你...
2013-3-14 19:37
0
雪    币: 149
活跃值: (150)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
.....
2013-3-14 20:17
0
游客
登录 | 注册 方可回帖
返回
//