Windows 95 System Programming SECRENTS学习笔记---第五章(3)

接下来VirtualAlloc处理来自fdwAllocationType参数的各种标志值。首先,它看看是否有未公开的0x80000000标志,那意味要分配2GB以上的内存。VirtualAlloc忽略MEM_TOP_DOWN标志。然后它再测试是否你只传入了MEM_COMMITMEM_RESERVED标志。任何其他的标志都会引发调试版的一个警告信息。最后,函数代码调用mmPAGEToPC,那是一个辅助函数(下一节描述),把fdwProtect参数标志转换为VMM_PageReserve所使用的标志。

 

这时候,函数兵分两路。如果不在乎哪一段内存要保留,就执行其中一路。如果调用者指定了某特定范围的内存,那么就执行另一路。不管是哪一路,如果内存要被保留,VirtualAlloc就调用Win32 Service 00010000,那是VMM’s _PageReserve函数的一个外包函数。保留这段内存之后,如果调用者还有指定MEM_COMMIT标志的话,VirtualAlloc就调用Win32 Service 00010001,那是VMM’s _PageCommit函数的一个外包函数。如果调用者指定了一个特定地址范围,VirtualAlloc会检查它是不是在0xC0000000VxD领域的起始处)之下。

 

整个函数代码中,VirtualAlloc不断周到的检查返回至_PageReserve_PageCommit。如果任何事情失败,它就会产生一个调试诊断信息,然后从某个唯一出口退出。该出口处会释放先前保留的内存。

VirtualAlloc函数的虚拟代码

// Parameters

//   LPVOID  lpvAddress

//   DWORD  cbSize

//   DWORD  fdwAllocationType

//   DWORD  fdwProtect

// Locals:

//   DWORD   address, startPage

//   DWORD   sizeInPages

//   DWORD   pcFlags  // Return from mmPAGEToPC

//   BOOL     fReserve

 

if  ( cbSize > 0x7FC00000 )  // 2GB – 4MB

{

_DebugOut(“VirtualAlloc: dwSize too big/n/r”, SLE_WARNING

+ FstopOnRing3MemoryError);

InternalSetLastError( ERROR_NOT_ENOUGH_MEMORY );

return 0;

}

 

address = lpvAddress;

 

// Calculate how many pages will be spanned by this memory request

sizeInPage = lpvAddress & 0x00000FFF;

sizeInPage += cbSize;

sizeInPage += 0x00000FFF;

sizeInPage = sizeInPage >> 12;

 

startPage = PR_PRIVATE;  // 0x80000400 from VMM.INC This value can be either

                        // an actual page number or a PR_equate.

 

if  ( fdwAllocationType & 0x80000000 ) // Undocumented shared mem flag

{

startPage = PR_SHARED;  // 0x80000000 in VMM.INC

fdwAllocationType &= ~0x80000000;  // Don’t need this flag anymore

}

 

fdwAllocationType &= ~MEM_TOP_DOWN;  // Ignore the MEM_TOP_DOWN flag

 

// You can specify MEM_COMMIT and/or MEM_RESERVE, but no other flags

// (the Undocumented one above not with standing).

if  (      (fdwAllocationType != MEM_COMMIT)

     &&  (fdwAllocationType != MEM_RESERVE)

     &&  (fdwAllocationType != (MEM_RESERVE | MEM_COMMIT)) )

{

_DebugOut( “VirtualAlloc: bad flAllocationType/n/r”,

           SLE_WARNING + FstopOnRing3MemoryError );

InternalSetLastError( ERROR_INVALID_PARAMETER );

return 0;

}

 

// Convert the fdwProtect flags into the PC_flag values used by

// VMM.VXD Pseudocode follows this function

pcFlags = mmPAGEToPC(fdwProtect);

 

if ( pcFlags == -1 )   // Something Error

   return 0;

 

if ( lpvAddress == 0 )   // Don’t care where the memory is allocated.

{

// Reserve the memory block. startPage should be either

// PR_PRIVATE or PR_SHARED

lpvAddress = VxDCall( _PageReserve, startPage, sizeInPages, pcFlags );

 

if  ( lpvAddress == -1 )

{

    _DebugOut( “VirtualAlloc: reserver failed/n”,

               SLE_WARNING + FStopOnRing3MemoryError );

    InternalSetLastError( ERROR_NOT_ENOUGH_MEMORY );

    return 0;

}

 

// If  caller is just reserving, we’re finished.

if  ( !(fdwAllocationType & MEM_COMMIT) )

    return  lpvAddress;

 

// Caller has specified MEM_COMMIT

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值