Mdl内存实现之原理1

来源:互联网 发布:贪吃蛇算法 编辑:程序博客网 时间:2024/06/07 05:04

I/O Buffer需要分连续虚拟内存跨越不同的物理页,物理页可能不连续。 就需要MDL结构了。

功能是分配一个MDL内存,根据VirtualAddress和长度。如果是在IRP相关调用的话(IRP非空),则

连接此MDL到IRP的相关结构。具体见如下代码:

   ULONG allocateSize;

    USHORT fixedSize;
    PMDL mdl;
    ULONG size;
    PMDL tmpMdlPtr;


    ASSERT(Length);

    //
    // If the requested length is greater than 2Gb, then we're not going
    // to be able to map the memory, so fail the request.
    //


    if (Length & 0x80000000) {
        return NULL;
    }

    // Allocate an MDL from the lookaside list or pool as appropriate.
    //


    mdl = NULL;
    fixedSize = 0;
    size = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
    if (size > IOP_FIXED_SIZE_MDL_PFNS) {
        allocateSize = sizeof(MDL) + (sizeof(PFN_NUMBER) * size);
        if (allocateSize > MAXUSHORT) {
            return NULL;
        }

    } else {
        fixedSize = MDL_ALLOCATED_FIXED_SIZE;
        allocateSize =  sizeof(MDL) + (sizeof(PFN_NUMBER) * IOP_FIXED_SIZE_MDL_PFNS);
        mdl = (PMDL)ExAllocateFromPPLookasideList(LookasideMdlList);
    }


    if (!mdl) {
        mdl = ExAllocatePoolWithTag(NonPagedPool, allocateSize, ' ldM');
        if (!mdl) {
            return NULL;
        }
    }


    //
    // Now fill in the header of the MDL.

    MmInitializeMdl(mdl, VirtualAddress, Length);
    mdl->MdlFlags |= (fixedSize);
    //
    // Finally, if an IRP was specified, store the address of the MDL
    // based on whether or not this is a secondary buffer.
    //


    if (Irp) {
        if (!SecondaryBuffer) {
            Irp->MdlAddress = mdl;


        } else {
            tmpMdlPtr = Irp->MdlAddress;
            while (tmpMdlPtr->Next != NULL) {
                tmpMdlPtr = tmpMdlPtr->Next;
            }


            tmpMdlPtr->Next = mdl;
        }
    }


    return mdl;