【问题标题】:IPC shared memory std::vector in windowsWindows 中的 IPC 共享内存 std::vector
【发布时间】:2015-08-26 17:57:07
【问题描述】:

我有两个 win32 程序,它们通过 IPC 与一个 DLL 通信。我使用 MSVC ++,所以使用 CreateFileMapping 和 MapViewOfFile 是有意义的。我已经完成了一些代码,问题是当我的第二个程序启动并加载一个 DLL 并开始使用 DLL 时,一切都很好,IPC 通信进展顺利。当第一个程序启动并加载一个 DLL 并开始使用 DLL 并且第二个程序启动并加载一个 DLL 并开始使用 DLL 时,第二个程序停止通过 IPC 与 DLL 通信。 IPC 通信可能正在运行,但可能以错误的方式运行。它获得了大小和容量,但内容是垃圾。共享内存的内容是指针向量!我究竟做错了什么?我需要知道什么才能让这些工作正常吗?

//The sender writer
MainWindow::~MainWindow()
{
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);
}

void MainWindow::SetData(vector <SubWindow*> &iMainWin)
{
    hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(vector <SubWindow*>), TEXT("MyMappedMem"));

    if (hMapFile == NULL)
        return;

    vector <SubWindow*> *pBuf = reinterpret_cast<std::vector<SubWindow*>*> (MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(vector <SubWindow*>)));

    if (pBuf == NULL)
    {
        CloseHandle(hMapFile);
        return;
    }

    memcpy(pBuf, &iMainWin, sizeof(iMainWin));
    return;
}

//The reciever reader 
void DataWork()
{
    do{
       if (strcmp(pe32.szExeFile, "Win32Project.exe") == 0)
       {
           bProcessFound = true;
           break;
       }
     } while (Process32Next(hProcessSnap, &pe32));

     if (!bProcessFound)
     {
         MessageBox(NULL, TEXT("ERROR Process32Next Openning DLL"), TEXT("ERROR"), MB_OK);
         return;
     }
     else
     {
        HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, TEXT("MyMappedMem"));

        if (hMapFile == NULL)
        {
            MessageBox(NULL, TEXT("ERROR OpenFileMapping DLL"), TEXT("ERROR"), MB_OK);
            return;
        }

        vector<SubWindow*> *pBuf = reinterpret_cast<std::vector<SubWindow*>*> (MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(vector <SubWindow*>)));

        if (pBuf == NULL)
        {
            MessageBox(NULL, TEXT("ERROR MapViewOfFile DLL"), TEXT("ERROR"), MB_OK);
            CloseHandle(hMapFile);
            return;
        }

        for (int i = 0; i < buf->size(); i++)
            (*buf)[i]->value_access;

        UnmapViewOfFile(pBuf);
        CloseHandle(hMapFile);
     }
}

【问题讨论】:

  • 完全错了。向量的 sizeof 与该向量内的数据大小不同。尝试输出 100 个整数的向量的 sizeof。大概有 20 个字节,明白吗?你需要改变你在内存中保存数据的方式
  • 文件映射可能是错误的解决方案。你为什么要解决这个问题?

标签: c++ winapi ipc stdvector


【解决方案1】:

第一个程序中的指针在第二个程序中是无用的,反之亦然。您不能在程序 B 中使用来自程序 A 的指针,因为它们具有不同的虚拟内存空间。

【讨论】:

    【解决方案2】:

    尝试使用共享内存共享std::vector 几乎肯定是错误的。 std::vector 将从调用进程中分配内存,这将无法通过任何其他进程访问。此外,任何其他进程都无法访问指向本地地址的指针。

    此外,您需要使用互斥锁来协调对std::vector 的访问,而您没有这样做。

    在这种情况下,我看不出使用文本文件不够用的任何理由。

    【讨论】:

    • 当您想要实现 IPC 时,文本文件可能是最糟糕的主意。例如,谁来清理你扔在人行道上的垃圾?有哪些一致性保证?你如何表示修改?您如何发出信号,何时可以安全使用数据?更简单、更合适的方式:序列化数据并通过(命名的)管道传输。
    • 该示例没有使用任何实际的 IPC。除非绝对必要,否则应避免共享内存和 IPC。但是,是的,还有其他机制可以避免同步访问的复杂性,并提供更好的语义。
    • 示例确实使用 IPC。它以CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(vector &lt;SubWindow*&gt;), TEXT("MyMappedMem")) 开头,并被重新映射到同一模块的另一个实例(在另一个进程中)。
    • 不,它没有。该示例建立了共享内存,但并未将其用于 IPC。没有进程正在通信。错误示例所做的是尝试共享在第一个进程中实例化的std::vector,在这种情况下,简单的文本格式就足够了。如果您认为我错了,请写一个答案,描述您将如何使用套接字或命名管道重写示例。
    • 您误解了这个例子。代码被编译成 DLL。此 DLL 链接到两个单独的进程。其中一个调用SetData,另一个进程调用DataWork。从两个进程访问相同的文件映射对象。这称为 IPC。它的实现方式没有按预期工作。尽管如此,IPC 是记录在案的意图。
    猜你喜欢
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    • 2011-07-23
    • 2011-07-18
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    相关资源
    最近更新 更多