общая отображенная память между двумя процессами не обновляется при редактировании - PullRequest
0 голосов
/ 25 февраля 2019

Я использую c ++ на windows и создаю простой метод для связи между двумя процессами

первый процесс создает отображенную память, записывает в нее первое сообщение и дублирует дескриптор для другого процесса (отображенная память не имеет названия) код выглядит следующим образом:

hMapped = CreateFileMappingA(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 1000, "my_shared_memory");
if (!hMapped)
{
    cout << "[!] failed to create the shared mapped memory with error : " << GetLastError() << endl;
    getchar();
}
char *shared_buffer = (char*)MapViewOfFile(hMapped, FILE_MAP_ALL_ACCESS, 0, 0, mapped_memory_size);

, затем другой процесс получает дескриптор, открывает представление и извлекает первый буфер, записанный

, затем он циклически проверяет каждые 6секунд для новых операций записи и работы с ними

Я пишу из первого процесса следующим образом:

std::lock_guard<std::mutex> lock(mtx);
RtlSecureZeroMemory(shared_buffer, mapped_memory_size);
shared_buffer[0] = 'n'; // it's a hint for the other process
memcpy(shared_buffer + 1, this->stuff.get_data().c_str(), this->stuff.get_data().size() + 1);

, но буфер не обновляется для второго процесса, это первый буфер

это код во втором процессе:

HANDLE shared_memory = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, "my_shared_memory");
char *shared_buffer = (char*)MapViewOfFile(shared_memory, FILE_MAP_ALL_ACCESS, 0, 0, 1000);

utils::command_line_parser cmd_parser;
cmd_parser.parse(std::string((char*)shared_buffer + 1));
if (!cmd_parser.valid()) { // I get that they are valid and I verify that
    printf("failed to parse the arguments !");
    return TRUE;
}
while(true)
{
    Sleep(6000);
    // CloseHandle(shared_memory);
    // shared_memory = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, "my_shared_memory");
    // shared_buffer = (char*)MapViewOfFile(shared_memory, FILE_MAP_ALL_ACCESS, 0, 0, 1000);
    MessageBoxA(0, (char*)shared_buffer, "message", 0);
    char res = shared_buffer[0];
    switch (res)
    {
    case 'q' :
        // do some stuff
    case 'n' :
        // do some stuff
        break;
    default:
        break;
    }

1 Ответ

0 голосов
/ 25 февраля 2019

Вот пример именованного приложения с общей памятью, которое, похоже, работает с Visual Studio 2015. Приложение может быть запущено как записывающее устройство в область памяти или считывающее устройство из области памяти в зависимости от указанного аргумента командной строки.

Глядя на документацию Microsoft, похоже, что разделение дескриптора требует разветвления процесса. CreateFileMappingA функция и из вашей первоначальной публикации и вопроса, который, кажется, не соответствует тому, что вы делаете.

Несколько процессов могут совместно использовать представление одного и того же файла, используя одинобщий объект сопоставления файлов или создание отдельных объектов сопоставления файлов, поддерживаемых одним и тем же файлом.Один объект сопоставления файлов может совместно использоваться несколькими процессами посредством наследования дескриптора при создании процесса, дублирования дескриптора или открытия объекта сопоставления файлов по имени.Для получения дополнительной информации см. Функции CreateProcess, DuplicateHandle и OpenFileMapping.

В следующем примере, используя именованную область общей памяти, я начал с исходного кода примера в CreateFileMapping, MapViewOfFile,справиться с утечкой c ++ однако, будучи ленивым, я просто создал один исходный файл, консольное приложение Windows, которое я мог запустить как два разных процесса с различным поведением.

Файл исходного кода, который используется для выполнения в дваразличные способы:

#include "stdafx.h"

#include <conio.h>
#include <iostream>

#define BUF_SIZE 256
TCHAR szName[] = TEXT("MyFileMappingObject");

int main(int argc, char **argv)
{
    HANDLE hMapFile;
    LPCTSTR pBuf;
    int     iInstance = 0;
    TCHAR szMsgFmt[] = TEXT("Message from first process %d.");

    if (argc > 1) {
        iInstance = atoi(argv[1]);
    }
    hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // use paging file
        NULL,                    // default security
        PAGE_READWRITE,          // read/write access
        0,                       // maximum object size (high-order DWORD)
        BUF_SIZE,                // maximum object size (low-order DWORD)
        szName);                 // name of mapping object

    DWORD lastError = GetLastError();
    if (hMapFile == NULL)
    {
        _tprintf(TEXT("Could not create file mapping object (%d).\n"),
            GetLastError());
        std::cin.get();
        return 1;
    }
    pBuf = (LPTSTR)MapViewOfFile(hMapFile,   // handle to map object
        FILE_MAP_ALL_ACCESS, // read/write permission
        0,
        0,
        BUF_SIZE);

    if (pBuf == NULL)
    {
        _tprintf(TEXT("Could not map view of file (%d).\n"),
            GetLastError());

        CloseHandle(hMapFile);

        std::cin.get();
        return 1;
    }


    for (int i = 1; i < 4; i++) {
        if (iInstance > 0) {
            MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
        }
        else {
            TCHAR szMsg[128] = { 0 };
            wsprintf (szMsg, szMsgFmt, i);
            std::cout << "Copying text into shared memory " << i << std::endl;
            CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
            std::cout << "Waiting " << std::endl;
            _getch();
        }
    }
    CloseHandle(hMapFile);


    UnmapViewOfFile(pBuf);
    return 0;
}

Пакетный файл 1 и пакетный файл 2 для запуска одного и того же исполняемого файла в качестве двух разных процессов.

shared_mem

pause

и

shared_mem  1

pause

и измененныйstdafx.h include file.

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

#include "targetver.h"

#include <Windows.h>
#include <WinUser.h>
#include <stdio.h>
#include <tchar.h>



// TODO: reference additional headers your program requires here

Скомпилируйте исходный файл приложения, а затем запустите первый bat-файл, который запустится, поместите некоторый текст в область общей памяти и подождите.Затем запустите второй файл bat, который будет читать текст из области общей памяти.

Что я увидел, если вы нажмете кнопку Ok в отображаемом диалоговом окне из второго файла bat, вы увидите то же самоесообщение снова.

Однако если вы затем перейдете к окну первого файла bat и нажмете клавишу ввода, чтобы сгенерировать следующее сообщение, а затем вернетесь к диалогу, созданному вторым файлом bat, вы увидите, что онобудет читать обновленную строку.

Все это использует именованный общий файл.Не пытался использовать дескриптор общей памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...