Доступ к отображению файла с помощью другой функции - PullRequest
0 голосов
/ 12 июля 2011

Здравствуйте, у меня есть process1, который правильно создает и сопоставляет файл (mmap для windows). Я могу корректно получить доступ к данным mmap и записать в него другой процесс, который я могу прочитать.

Проблема возникает, когда я хочу получить доступ к сопоставленному файлу с помощью другой функции process1.

Я создаю сопоставленный файл следующим образом:

TCHAR szName[]=TEXT("Global\\MyFileMappingObject");

int mancontrol(void* pvBrick, HANDLE hMutex);

int main()
{
    //Handels and vars for IPC
    HANDLE hMapFile;
    LPCTSTR pBuf;
    char szMsg[256];
    string dataStr = "";

     //Create file mapping
     hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUF_SIZE, szName);
     if (hMapFile == NULL)
     {
        printf("Failed to create a mmap \n");

        return 1;
     }

    //Map file(MapViewOfFile) and return pointer of the mapped file(file view)
    pBuf = (LPTSTR) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
    if (pBuf == NULL)
    {
       printf("Failed to map mmap");
       CloseHandle(hMapFile);

      return 1;
   }

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

int mancontrol(void* pvBrick, HANDLE hMutex, LPCSTR pBuf)
{
    char Msg[256];
    string dataString = "";
    dataString = "AAAA en BBBB";
    strcpy(Msg, dataString.c_str());
    CopyMemory((PVOID)pBuf, Msg,  strlen(Msg));
    dataString = "";

Я не получаю новое сообщение об ошибке, но процесс2 не может прочитать данные (в основном данные, которые я посылаю туда, процесс2 может прочитать). Мне нужно открыть сопоставленный файл в функции и сопоставить его снова? Или что-то не так с моим аргументом?

Ответы [ 2 ]

1 голос
/ 12 июля 2011

Я бы сказал, что догадка Берт-Джана верна.

Вы можете выполнить сопоставление с файлом реального диска, передав реальный дескриптор файла из CreateFile () в качестве первого параметра CreateFileMapping (), затем сопоставленный файл сохраняется и его данные останутся доступными.

С другой стороны, вы передали INVALID_HANDLE_VALUE в качестве первого параметра, который создает временный файл памяти.Как только нет сопоставлений с файлом, он будет удален.Когда второй процесс создает отображение, он получает новый файл.

В реальной жизни два процесса могут работать дольше, поэтому это может не быть проблемой.

Ради интереса я запустил программу быстрого сэмпла.Если программа называется fmap.exe (как в моей тестовой версии), запустите один экземпляр как «fmap server», а второй как «fmap» (который является клиентом.

Введите текст в клиент ибудет распечатан сервером.

// fmap.cpp 

#include <Windows.h>
#include <iostream>
#include <string>
#include <algorithm>
#include <stdexcept>

// convenience class to manage a mutex
class CMutex
{
public:
    CMutex(const char *szName)
    {
        std::string sName = std::string("MUTEX_") + szName;
        m_hMutex = ::CreateMutex(
                        NULL,           //  __in_opt  LPSECURITY_ATTRIBUTES lpMutexAttributes,
                        FALSE,          //  __in      BOOL bInitialOwner,
                        sName.c_str()); //  __in_opt  LPCTSTR lpName
        if (!m_hMutex)
            throw std::runtime_error("Failed to create mutex");
    }
    ~CMutex()
    {
        if (m_hMutex)
            ::CloseHandle(m_hMutex);
    }
    void Lock()
    {
        ::WaitForSingleObject(m_hMutex, INFINITE);
    }
    void Unlock()
    {
        ::ReleaseMutex(m_hMutex);
    }

private:
    HANDLE m_hMutex;
};

// convenience class to lock a mutex and unlock it when it
// goes out of scope.
class CAutoLock
{
public:
    CAutoLock(CMutex &m)
    : m_mutex(m)
    {
        m_mutex.Lock();
    }
    ~CAutoLock()
    {
        m_mutex.Unlock();
    }
private:
    CMutex &m_mutex;
};

// Class to manage a mapped file
// uses the same name for the file and the mutex
class CMappedFile 
{
public:
    CMappedFile(const char *szName)
    : m_hMapFile(NULL)
    , m_szBuff(NULL)
    , m_mutex(szName)
    {
        m_hMapFile = CreateFileMapping(
                            INVALID_HANDLE_VALUE,  // HANDLE hFile,
                            NULL,                  // LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
                            PAGE_READWRITE,        // DWORD flProtect,
                            0,                     // DWORD dwMaximumSizeHigh,
                            nBuffSize,             // DWORD dwMaximumSizeLow,
                            szName);               // LPCTSTR lpName 
        if (!m_hMapFile)
            throw std::runtime_error("Failed to create mapping");

        m_szBase = 
            reinterpret_cast<char *>(
                    MapViewOfFile(
                            m_hMapFile,           //  HANDLE hFileMappingObject,
                            FILE_MAP_ALL_ACCESS,  //  DWORD dwDesiredAccess,
                            0,                    //  DWORD dwFileOffsetHigh,
                            0,                    //  DWORD dwFileOffsetLow,
                            nBuffSize));          //  DWORD dwNumberOfBytesToMap
        if (!m_szBase)
            throw std::runtime_error("Failed to create view");

        // reserve first few bytes of the file for a length variable.  
        // The rest is the buffer.
        m_szBuff = m_szBase + sizeof(size_t);
    }

    ~CMappedFile()
    {
        if (m_szBase)
        {
            UnmapViewOfFile(m_szBase);
        }
        if (m_hMapFile)
        {
            CloseHandle(m_hMapFile);
        }
    }

    // add a string to the mapped file
    void Put(const std::string &sVal)
    {
        // lock mutex
        CAutoLock l(m_mutex);

        // create reference to beginning of the buffer
        size_t &nLength = *reinterpret_cast<size_t *>(m_szBase);

        // check for overflow
        if (nLength + sVal.length() >= nBuffSize)
            throw std::runtime_error("Buffer Overflow");

        // copy string to buffer and increment length
        std::copy(sVal.begin(), sVal.end(), m_szBuff + nLength);
        nLength += sVal.length();
    }

    // read a string from the mapped file and
    // clear the length field, indicating that
    // this data has been read.
    std::string Get()
    {   
        // lock mutex
        CAutoLock l(m_mutex);

        // create reference to beginning of the buffer
        size_t &nLength = *reinterpret_cast<size_t *>(m_szBase);

        std::string sVal;
        if (nLength)
        {
            // if anything is in the buffer read ot
            sVal.assign(m_szBuff, nLength);

            // reset length as we've read the buffer
            nLength = 0;
        }
        return sVal;
    }

private:
    HANDLE m_hMapFile;
    char * m_szBase;
    char * m_szBuff;
    CMutex m_mutex;

    enum { 
        nBaseSize=1024,                     // whole file size
        nBuffSize=nBaseSize-sizeof(size_t)  // buffer size, after size has been reserved
    };
};

void DoClient(CMappedFile &m);
void DoServer(CMappedFile &m);

int main(int argc, char* argv[])
{
    try
    {
        const char szUniqueName[] = "CA249329_ACAE_11E0_9594_6CF0494804C2";
        CMappedFile m(szUniqueName);

        std::string sServer("server");
        if (argc==2 && sServer==argv[1])
            DoServer(m);
        else
            DoClient(m);
    }
    catch (std::exception &e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

void DoClient(CMappedFile &m)
{
    std::cout << "Client running\n\n";
    std::string s;
    while (std::getline(std::cin, s))
        m.Put(s);
}

void DoServer(CMappedFile &m)
{
    std::cout << "Server running\n\n";
    while (1)
    {
        std::string s = m.Get();
        if (s.length())
            std::cout << s << std::endl;
    }
}
1 голос
/ 12 июля 2011

Похоже, что процесс, создающий отображение памяти, завершается до того, как другой процесс получит возможность связать его с отображением, и в этом случае я не удивлюсь, если Windows удалит отображение.Как все упорядочено по времени в вашей заявке?

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