Win3内存管理之私有内存跟共享内存的申请与释放

      Win3内存管理之私有内存跟共享内存的申请与释放

一丶内存简介私有内存申请

  通过上一篇文章.我们理解了虚拟内存与物理内存的区别. 那么我们有API事专门申请虚拟内存与物理内存的.

有私有内存跟共享内存. 私有内存的意思就是这块内存申请只在本进程的物理页当中. 共享内存就是这个物理页 A B两个进程都可以使用.

私有内存申请API

  VirtualAlloc / virtualAllocEx

LPVOID VirtualAlloc(  
LPVOID lpAddress, 你要申请的地址.可以指定地址.但是物理页我们不知道那个地址是否存在.所以一般为0 SIZE_T dwSize, 申请内存的大小.一般为一个页.虽然MSDN说了一Byte(字节) 为主. 但是我们知道物理内存是一个页.所以申请一个页即可. DWORD flAllocationType, 申请内存的类型. 是这样的.我们申请内存在物理页. 可以有两种类型.一种类型就是物理内存直接申请.一种就是物理内存占位置.并不申请.一般用第一种. DWORD flProtect 内存的状态.我们申请的内存状态是可读的 还是可写的. 还是可读写的.

virtualAllocEx 是远程内存申请.就是说我们可以通过指定的进程. 给这个指定进程申请内存.

new malloc的区别. 请注意.真正申请内存的其实是API. 而new malloc 是申请堆内存. 意思就是说. new malloc其实就是在已申请的内存上面划分出来了一块虚拟内存给你使用.

不管你使用没使用. 而且new关键字本质也就是malloc 只不过可以进行构造. 而 malloc的底层是通过 HeapAlloc申请的. 并没有进0环(内核)

二丶共享内存申请

1.共享内存申请

  共享内存其实就是物理页可以共享使用了. A进程申请物理页往这个物理页填写内容. B进程就可以读取了.

我们具体的API

  1. 申请物理页内存API

    

HANDLE CreateFileMapping(  HANDLE hFile,                       文件映射.申请的物理页可以跟文件相映射.如果不需要文件只申请物理页则不需要.
  LPSECURITY_ATTRIBUTES lpAttributes,                 SD安全属性,每个内核对象都需要的安全属性
  DWORD flProtect,                                    权限.你申请的这个物理页是可读的可写的还是可读写.
  DWORD dwMaximumSizeHigh,                                     申请内存的高32位. windows为了支持64我操作系统.所以给了高低32位来保存地址. 如果是32位地址.则不需要.填0即可.
  DWORD dwMaximumSizeLow,                             低32位,你要申请的物理页内存的大小
  LPCTSTR lpName                                     进程共享物理页的名字.如果希望这个物理页B进程可以使用则需要给一个名字.
返回值: 返回物理页句柄索引.

有创建物理页 也有打开物理页 主要是B进程使用.

  

HANDLE OpenFileMapping(  DWORD dwDesiredAccess,  // access mode
  BOOL bInheritHandle,    // inherit flag
  LPCTSTR lpName          // object name);

当然如果B进程使用一样可以使用CreateFileMaping. 只不过会返回文件对象已经存在的错误.

2.线性地址(虚拟地址) 关联物理页.

  上面申请了物理页.那么我们还需要将这个物理页映射到线性地址.需要的API如下.

LPVOID MapViewOfFile(
  HANDLE hFileMappingObject,   // 物理页句柄
  DWORD dwDesiredAccess,       // 线性地址访问权限,注意跟物理页最好一直.或者比物理页更严格.
  DWORD dwFileOffsetHigh,      // 映射线性地址的偏移位置 高32位
  DWORD dwFileOffsetLow,       // 低32位
  SIZE_T dwNumberOfBytesToMap  // 内存映射结束位置;

3.取消关联

     

BOOL UnmapViewOfFile(  LPCVOID lpBaseAddress   // starting address);  虚拟地址

关闭物理页映射则使用CloseHandle. PS: 知识 引用计数-1. 为0了则会关闭.

具体代码如下.

A进程B进程一样. A进程写入. B进程写入.

  

// A.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

int main()
{
    getchar();
    //A进程 申请物理页
    HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x1000, TEXT("共享内存"));


    //2.映射虚拟内存(线性地址的)
    LPVOID lpBuf = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0x1000);

    // A进程写内存
    *(char *)lpBuf = 'a';  //写内存
    printf("写入内存为a 
");
    getchar();

    UnmapViewOfFile(lpBuf);
    CloseHandle(hMap);
    return 0;
}

B进程代码:

  

// A.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

int main()
{
    getchar();
    //A进程 申请物理页
    HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x1000, TEXT("共享内存"));


    //2.映射虚拟内存(线性地址的)
    LPVOID lpBuf = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0x1000);

    // A进程写内存
    
    printf("读取内存为 %c 
",*(char *)lpBuf);
    getchar();

    UnmapViewOfFile(lpBuf);
    CloseHandle(hMap);
    return 0;
}

这样就实现了物理页共享.

原文地址:https://www.cnblogs.com/iBinary/p/9581863.html