如何读取映射文件中的结构矢量?

问题描述

我有2个程序,一个程序使用Windows API获取所有进程信息,并将它们存储在这样的结构向量中:@H_404_1@

struct Info{
  int pid,ppid;
  char exeName[256];
}

当我用数据填充结构时,我将back_pushing结构保留在向量中。 现在,我尝试使用memcpy()来存储映射文件中的数据,但是在第二个程序中无法正确读取它。您能帮我弄清楚如何正确读取数据吗?@H_404_1@

代码程序1:@H_404_1@

    #define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>
#include <Tlhelp32.h>
#include <vector>

struct InfoProces {
    DWORD pid;
    DWORD ppid;
    char  exeName[256];
};

int main(){
    HANDLE hProcesses;
    PROCESSENTRY32 pe32;

    hProcesses = Createtoolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if (hProcesses == INVALID_HANDLE_VALUE)
    {
        printf("Createtoolhelp32Snapshot Failed. err = %d",GetLastError());
        return -1;
    }
    
    pe32.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hProcesses,&pe32)) {
        printf("Process32First Failed. err = %d",GetLastError());
        CloseHandle(hProcesses);
        return -1;
    }

    
    HANDLE hdata = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,1024 * 1024,"data");
    if (hdata == NULL) {
        printf("Can't create a file mapping. err = %d",GetLastError());
        return -1;
    }

    unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata,FILE_MAP_WRITE,0);
    if (pdata == NULL) {
        printf("cant get pointer to mapping file. err = %d",GetLastError());
        return -1;
    }

    

    do {
        InfoProces pi;
        pi.pid = pe32.th32ProcessID;
        pi.ppid = pe32.th32ParentProcessID;
        strcpy(pi.exeName,pe32.szExeFile);
        
        
    } while (Process32Next(hProcesses,&pe32));
    

    getchar();
    CloseHandle(hProcesses);
    return 0;

代码程序2:@H_404_1@

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <vector>
#include <stdio.h>

struct InfoProces {
    DWORD pid;
    DWORD ppid;
    char  exeName[256];
};

int main() 
{
    HANDLE hdata = OpenFileMapping(FILE_MAP_ALL_ACCESS,false,"data");

    unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata,FILE_MAP_READ,0);
    if (pdata == NULL) {
        printf("cant get pointer to mapped file. err = %d",GetLastError());
        return -1;
    }
    std::vector<InfoProces>processes;

    memcpy(&processes,pdata,sizeof(data));

    for (std::vector<InfoProces>::iterator i = processes.begin(); i < processes.end(); i++)
        printf("Process[%d](parinte[%d]): %s\n",i->pid,i->ppid,i->exeName);
    
    return 0;
}

解决方法

正如评论所指出的那样,您已经获得了映射视图的起始地址(pdata),您只能使用pdata进行内存共享,而不能使用该进程的任何堆栈地址。 尝试将InfoProces的内存复制到程序1中的pdata

memcpy(pdata,&pi,sizeof(InfoProces));

此外,在程序2中,您未设置矢量的大小,应将&processes替换为processes.data()。您还需要知道在程序1中添加的数组的大小:

std::vector<InfoProces> processes;
processes.resize(count);
memcpy(processes.data(),pdata,sizeof(InfoProces)*count);

以下代码对我有用。

程序1 :(记录InfoProces的计数并将其保存在pdata开头的DWORD中)

...
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata,FILE_MAP_WRITE,0);
if (pdata == NULL) {
    printf("cant get pointer to mapping file. err = %d",GetLastError());
    return -1;
}

unsigned char* begin = pdata;

//offset a size of DWORD;
DWORD count = 0;
pdata += sizeof(DWORD);

do {
    InfoProces pi;
    pi.pid = pe32.th32ProcessID;
    pi.ppid = pe32.th32ParentProcessID;
    strcpy(pi.exeName,pe32.szExeFile);
    memcpy(pdata,sizeof(InfoProces));
    pdata += sizeof(InfoProces);
    count++;
} while (Process32Next(hProcesses,&pe32));

memcpy(begin,&count,sizeof(DWORD));

getchar();
UnmapViewOfFile(begin);
CloseHandle(hdata);
CloseHandle(hProcesses);
...

程序2:

...
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata,FILE_MAP_READ,0);
if (pdata == NULL) {
    printf("cant get pointer to mapped file. err = %d",GetLastError());
    return -1;
}
unsigned char* begin = pdata;
DWORD count = 0;
memcpy(&count,sizeof(DWORD));
pdata += sizeof(DWORD);

std::vector<InfoProces> processes;
processes.resize(count);
memcpy(processes.data(),sizeof(InfoProces)*count);

for (std::vector<InfoProces>::iterator i = processes.begin(); i < processes.end(); i++)
    printf("Process[%d](parinte[%d]): %s\n",i->pid,i->ppid,i->exeName);
UnmapViewOfFile(begin);
CloseHandle(hdata);
...

最后,不要忘记关闭句柄并取消映射地址。