前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AWE 内存管理

AWE 内存管理

作者头像
我与梦想有个约会
发布2023-10-21 14:35:43
2300
发布2023-10-21 14:35:43
举报
文章被收录于专栏:jiajia_deng

AWE (Address Windows Extension) 可以使用开启 PAE 后普通应用程序无法使用到的内存,这部分内存系统可能无法识别,但通过 AWE 则可以完美访问。操作 AWE 内存的具体步骤如下,大部分内容来自北风网视频教程。 1、开窗 VirtualAlloc + MEM_PHYSICAL,明确告知系统,这段保留的空间未来将存放我自己申请的物理内存。 2、分配物理内存 AllocateUserPhysicalPages,按页面个数来分配,不是按字节分配的,最少一个页面 4K 的物理内存。 3、将申请好的物理内存映射到窗口中(相当于提交)MapUserPhysicalPages。 4、对已经提交的内存读写… 5、释放物理内存页面。

注意事项

1、打开 PAE 后并不是所有应用程序都可以访问大于 4GB 的内存,要访问需要通过 AWE 打开 PAE 高出 4GB 地址空间的内存,AWE 但不仅限于打开 PAE 后多出来的内存,当需要自己操作物理页面的时候,都可以用到它。(顺网无盘的产品利用系统未识别的内存做缓存就是这个原理) 2、使用 AWE 一样需要锁定内存页的权限。

代码及配图

图中表示了下面代码对内存操作的步骤:

代码语言:javascript
复制
#define _WIN32_WINNT 0x0502
#include <tchar.h>
#include <windows.h>
#include <stdio.h>

#define MEMORY_REQUESTED 1024 * 1024 * 1024 //1GB

BOOL LoggedSetLockPagesPrivilege(HANDLE hProcess, BOOL bEnable);

void _cdecl main()
{
    BOOL bResult;                   // generic Boolean value
    ULONG_PTR NumberOfPages;        // number of pages to request
    ULONG_PTR NumberOfPagesInitial; // initial number of pages requested
    ULONG_PTR *aPFNs1;               // page info; holds opaque data
    ULONG_PTR *aPFNs2;               // page info; holds opaque data
    PVOID lpMemReserved;            // AWE window
    SYSTEM_INFO sSysInfo;           // useful system information
    int PFNArraySize;               // memory to request for PFN array
    TCHAR* pszData;
    TCHAR  pszReadData[100];

    MEMORYSTATUSEX ms = { sizeof(MEMORYSTATUSEX) };
    GlobalMemoryStatusEx(&ms);

    //  LoggedSetLockPagesPrivilege(::GetCurrentProcess(),TRUE);

    //1 "开窗"
    lpMemReserved = VirtualAlloc(NULL, MEMORY_REQUESTED, MEM_RESERVE  MEM_PHYSICAL, PAGE_READWRITE);
    //计算需要的物理页面大小 以及物理页面需要的页表数组大小
    GetSystemInfo(&sSysInfo);  // fill the system information structure
    NumberOfPages = (MEMORY_REQUESTED + sSysInfo.dwPageSize - 1) / sSysInfo.dwPageSize;
    PFNArraySize = NumberOfPages * sizeof(ULONG_PTR);
    //2 准备物理页面的页表数组数据
    aPFNs1 = (ULONG_PTR *)HeapAlloc(GetProcessHeap(), 0, PFNArraySize);
    aPFNs2 = (ULONG_PTR *)HeapAlloc(GetProcessHeap(), 0, PFNArraySize);
    NumberOfPagesInitial = NumberOfPages;
    //3 分配物理页面
    bResult = AllocateUserPhysicalPages(GetCurrentProcess(), &NumberOfPages, aPFNs1);
    bResult = AllocateUserPhysicalPages(GetCurrentProcess(), &NumberOfPages, aPFNs2);
    //4 映射第一个1GB到保留的空间中
    bResult = MapUserPhysicalPages(lpMemReserved, NumberOfPages, aPFNs1);
    pszData = (TCHAR*)lpMemReserved;
    _tcscpy(pszData, _T("这是第一块物理内存"));
    //5 映射第二个1GB到保留的空间中
    bResult = MapUserPhysicalPages(lpMemReserved, NumberOfPages, aPFNs2);
    _tcscpy(pszData, _T("这是第二块物理内存"));
    //6 再映射回第一块内存,并读取开始部分
    bResult = MapUserPhysicalPages(lpMemReserved, NumberOfPages, aPFNs1);
    _tcscpy(pszReadData, pszData);
    //7 取消映射
    bResult = MapUserPhysicalPages(lpMemReserved, NumberOfPages, NULL);
    //8 释放物理页面
    bResult = FreeUserPhysicalPages(GetCurrentProcess(), &NumberOfPages, aPFNs1);
    bResult = FreeUserPhysicalPages(GetCurrentProcess(), &NumberOfPages, aPFNs2);
    //9 释放保留的"窗口"空间
    bResult = VirtualFree(lpMemReserved, 0, MEM_RELEASE);
    //10 释放页表数组
    bResult = HeapFree(GetProcessHeap(), 0, aPFNs1);
    bResult = HeapFree(GetProcessHeap(), 0, aPFNs2);

    _tsystem(_T("PAUSE"));

}

/*****************************************************************
LoggedSetLockPagesPrivilege: a function to obtain or
release the privilege of locking physical pages.

Inputs:

HANDLE hProcess: Handle for the process for which the
privilege is needed

BOOL bEnable: Enable (TRUE) or disable?

Return value: TRUE indicates success, FALSE failure.

*****************************************************************/
BOOL
LoggedSetLockPagesPrivilege(HANDLE hProcess,
BOOL bEnable)
{
    struct {
        DWORD Count;
        LUID_AND_ATTRIBUTES Privilege[1];
    } Info;

    HANDLE Token;
    BOOL Result;

    // Open the token.

    Result = OpenProcessToken(hProcess,
        TOKEN_ADJUST_PRIVILEGES,
        &Token);

    if (Result != TRUE)
    {
        printf("Cannot open process token.\n");
        return FALSE;
    }

    // Enable or disable?

    Info.Count = 1;
    if (bEnable)
    {
        Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
    }
    else
    {
        Info.Privilege[0].Attributes = 0;
    }

    // Get the LUID.

    Result = LookupPrivilegeValue(NULL,
        SE_LOCK_MEMORY_NAME,
        &(Info.Privilege[0].Luid));

    if (Result != TRUE)
    {
        printf("Cannot get privilege for %s.\n", SE_LOCK_MEMORY_NAME);
        return FALSE;
    }

    // Adjust the privilege.

    Result = AdjustTokenPrivileges(Token, FALSE,
        (PTOKEN_PRIVILEGES)&Info,
        0, NULL, NULL);

    // Check the result.

    if (Result != TRUE)
    {
        printf("Cannot adjust token privileges (%u)\n", GetLastError());
        return FALSE;
    }
    else
    {
        if (GetLastError() != ERROR_SUCCESS)
        {
            printf("Cannot enable the SE_LOCK_MEMORY_NAME privilege; ");
            printf("please check the local policy.\n");
            return FALSE;
        }
    }

    CloseHandle(Token);

    return TRUE;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 注意事项
  • 代码及配图
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档