合并 Win32 的虚拟分配占位符

如何解决合并 Win32 的虚拟分配占位符

我试图围绕 Win32 的虚拟分配概念占位符以及如何合并它们。

不幸的是,我在网上找不到任何示例,尽管尝试了各种变体,但我的代码仍无法正常工作。

有人能指出我遗漏的地方吗?

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

// Helpers
// -------------------------------------------------------------------------

static void
get_page_size(size_t *page_size)
{
    SYstem_INFO system_info;

    GetSystemInfo(&system_info);
    *page_size = system_info.dwPageSize;
}

static void
touch_pages(void *buf,size_t size,size_t page_size)
{
    size_t i;

    for (i = 0; i < size; i += page_size) {
        void *ptr;

        ptr = (void *)((uintptr_t)buf + i);
        *((size_t *)ptr) = i;
    }
}

static void
check_pages(void *buf,size_t page_size)
{
    size_t i;
    size_t good;

    good = 0;
    for (i = 0; i < size; i += page_size) {
        void *ptr;

        ptr = (void *)((uintptr_t)buf + i);
        if (*((size_t *)ptr) != i) {
            printf("invalid data!\n");
            exit(0);
        }

        ++good;
    }

    printf("all good!\n");
}

static void
print_last_error(void)
{
    char buf[256];

    FormatMessageA(
        FORMAT_MESSAGE_FROM_SYstem | FORMAT_MESSAGE_IGnorE_INSERTS,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),buf,(sizeof(buf) / sizeof(char)),NULL);

    printf("%s\n",buf);
}

// -------------------------------------------------------------------------

int
main(void)
{
    size_t page_size;
    ULARGE_INTEGER alloc_size;

    get_page_size(&page_size);
    alloc_size.QuadPart = 0x10000000;

    // PART 1
    // -------------------------------------------------------------------------

    // Allocate 256 MB at a fixed address.
    // This is done by reserving a block of virtual addresses,creating
    // paging-backed sections,and mapping them onto the allocation block.

    void *addr_1 = (void *)0x10000000; // Aligned with allocation granularity.

    void *placeholder_1 = VirtualAlloc2(
        GetCurrentProcess(),addr_1,(size_t)alloc_size.QuadPart,MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,PAGE_NOACCESS,0
    );

    if (placeholder_1 == NULL) {
        printf("placeholder_1: VirtualAlloc2 Failed\n");
        print_last_error();
        exit(0);
    }

    HANDLE section_1 = CreateFileMappingA(
        INVALID_HANDLE_VALUE,PAGE_READWRITE,alloc_size.HighPart,alloc_size.LowPart,NULL
    );

    if (section_1 == NULL) {
        printf("section_1: CreateFileMappingA Failed\n");
        print_last_error();
        exit(0);
    }

    void *view_1 = MapViewOfFile3(
        section_1,GetCurrentProcess(),MEM_REPLACE_PLACEHOLDER,0
    );

    if (view_1 == NULL) {
        printf("view_1: MapViewOfFile3 Failed\n");
        print_last_error();
        exit(0);
    }

    // Touch each page just to make sure that they are fully committed.
    touch_pages(view_1,page_size);

    // PART 2
    // -------------------------------------------------------------------------

    // Grow the prevIoUs allocation by another 256 MB.
    // The exercise here is to try replicating Linux's `mremap()` by using
    // `MEM_COALESCE_PLACEHOLDERS`.
    // The idea is to reserve another block of virtual addresses just after
    // the first allocation block,merging both blocks into a single one,// creating another bunch of paging-backed sections,and mapping
    // all the pages onto the merged allocation block.

    void *addr_2 = (void *)0x20000000; // Aligned with allocation granularity.

    void *placeholder_2 = VirtualAlloc2(
        GetCurrentProcess(),addr_2,0
    );

    if (placeholder_2 == NULL) {
        printf("placeholder_2: VirtualAlloc2 Failed\n");
        print_last_error();
        exit(0);
    }

    // It seems that we first need to unmap or else the following call to
    // `VirtualFree()` complains about attempting to access an invalid address.
    if (!UnmapViewOfFile2(
            GetCurrentProcess(),view_1,MEM_PRESERVE_PLACEHOLDER
        ))
    {
        printf("view_1: UnmapViewOfFile2 Failed\n");
        print_last_error();
        exit(0);
    }

    if (!VirtualFree(
            placeholder_1,(size_t)alloc_size.QuadPart * 2,MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS
        ))
    {
        printf("placeholder_1: VirtualFree Failed\n");
        print_last_error();
        exit(0);
    }

    // Create a new allocation block that represents both prevIoUs blocks
    // merged into a single one.
    void *placeholder_3 = VirtualAlloc2(
        GetCurrentProcess(),MEM_RESERVE | MEM_REPLACE_PLACEHOLDER,0
    );

    if (placeholder_3 == NULL) {
        printf("placeholder_3: VirtualAlloc2 Failed\n");
        print_last_error();
        exit(0);
    }

    HANDLE section_2 = CreateFileMappingA(
        INVALID_HANDLE_VALUE,NULL
    );

    if (section_2 == NULL) {
        printf("section_2: CreateFileMappingA Failed\n");
        print_last_error();
        exit(0);
    }

    // This fails due to an attempt to access an invalid addres.
    void *view_1b = MapViewOfFile3(
        section_1,0
    );

    if (view_1b == NULL) {
        printf("view_1b: MapViewOfFile3 Failed\n");
        print_last_error();
        exit(0);
    }

    // This fails for the same reason if the prevIoUs mapping is commented.
    void *view_2b = MapViewOfFile3(
        section_2,0
    );

    if (view_2b == NULL) {
        printf("view_2b: MapViewOfFile3 Failed\n");
        print_last_error();
        exit(0);
    }

    // Check that we have the same data as the one we touched.
    check_pages(view_1,page_size);

    return 0;
}

解决方法

根据VirtualAlloc2MEM_REPLACE_PLACEHOLDER AllocationType 将占位符替换为普通的私有分配。所以只需注释 placeholder_3 行。替换占位符后不能MapViewOfFile3
以下代码适用于我。

int
main(void)
{
    size_t page_size;
    ULARGE_INTEGER alloc_size{};

    get_page_size(&page_size);
    //alloc_size.QuadPart = page_size;
    alloc_size.QuadPart = 0x10000000;

    // PART 1
    // -------------------------------------------------------------------------

    // Allocate 256 MB at a fixed address.
    // This is done by reserving a block of virtual addresses,creating
    // paging-backed sections,and mapping them onto the allocation block.

    void* addr_1 = (void*)0x10000000; // Aligned with allocation granularity.

    void* placeholder_1 = VirtualAlloc2(
        GetCurrentProcess(),addr_1,(size_t)alloc_size.QuadPart,MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,PAGE_NOACCESS,NULL,0
    );

    if (placeholder_1 == NULL) {
        printf("placeholder_1: VirtualAlloc2 failed\n");
        print_last_error();
        exit(0);
    }

    HANDLE section_1 = CreateFileMappingA(
        INVALID_HANDLE_VALUE,PAGE_READWRITE,alloc_size.HighPart,alloc_size.LowPart,NULL
    );

    if (section_1 == NULL) {
        printf("section_1: CreateFileMappingA failed\n");
        print_last_error();
        exit(0);
    }

    void* view_1 = MapViewOfFile3(
        section_1,GetCurrentProcess(),MEM_REPLACE_PLACEHOLDER,0
    );

    if (view_1 == NULL) {
        printf("view_1: MapViewOfFile3 failed\n");
        print_last_error();
        exit(0);
    }

    // Touch each page just to make sure that they are fully committed.
    //touch_pages(view_1,page_size);

    // PART 2
    // -------------------------------------------------------------------------

    // Grow the previous allocation by another 256 MB.
    // The exercise here is to try replicating Linux's `mremap()` by using
    // `MEM_COALESCE_PLACEHOLDERS`.
    // The idea is to reserve another block of virtual addresses just after
    // the first allocation block,merging both blocks into a single one,// creating another bunch of paging-backed sections,and mapping
    // all the pages onto the merged allocation block.

    //void* addr_2 = (void*)((PCHAR)addr_1 + alloc_size.QuadPart); // Aligned with allocation granularity.
    void* addr_2 = (void*)0x20000000; // Aligned with allocation granularity.

    void* placeholder_2 = VirtualAlloc2(
        GetCurrentProcess(),addr_2,0
    );

    if (placeholder_2 == NULL) {
        printf("placeholder_2: VirtualAlloc2 failed\n");
        print_last_error();
        exit(0);
    }

    // It seems that we first need to unmap or else the following call to
    // `VirtualFree()` complains about attempting to access an invalid address.
    if (!UnmapViewOfFile2(
        GetCurrentProcess(),view_1,MEM_PRESERVE_PLACEHOLDER
    ))
    {
        printf("view_1: UnmapViewOfFile2 failed\n");
        print_last_error();
        exit(0);
    }

    alloc_size.QuadPart *= 2;
    if (!VirtualFree(
        addr_1,MEM_RELEASE |MEM_COALESCE_PLACEHOLDERS
    ))
    {
        printf("placeholder_1: VirtualFree failed\n");
        print_last_error();
        exit(0);
    }

    // Create a new allocation block that represents both previous blocks
    // merged into a single one.
    /*void* placeholder_3 = VirtualAlloc2(
        GetCurrentProcess(),MEM_RESERVE | MEM_REPLACE_PLACEHOLDER,0
    );

    if (placeholder_3 == NULL) {
        printf("placeholder_3: VirtualAlloc2 failed\n");
        print_last_error();
        exit(0);
    }*/

    HANDLE section_2 = CreateFileMappingA(
        INVALID_HANDLE_VALUE,NULL
    );

    if (section_2 == NULL) {
        printf("section_2: CreateFileMappingA failed\n");
        print_last_error();
        exit(0);
    }

    // This fails due to an attempt to access an invalid addres.
    void* view_1b = MapViewOfFile3(
        section_2,0
    );

    if (view_1b == NULL) {
        printf("view_1b: MapViewOfFile3 failed\n");
        print_last_error();
        exit(0);
    }

    char* lpPtr = (char*)view_1b;
    lpPtr[0x20000000 - 1] = 'a';
    //// This fails for the same reason if the previous mapping is commented.
    //void* view_2b = MapViewOfFile3(
    //  section_2,//  GetCurrentProcess(),//  addr_2,//  0,//  (size_t)alloc_size.QuadPart,//  MEM_REPLACE_PLACEHOLDER,//  PAGE_READWRITE,//  NULL,//  0
    //);

    //if (view_2b == NULL) {
    //  printf("view_2b: MapViewOfFile3 failed\n");
    //  print_last_error();
    //  exit(0);
    //}

    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?