2016-10-25 50 views
0

我寫了兩個小程序。將字符串寫入共享內存的C++程序,以及從共享內存讀取字符串並將其寫入控制檯的C#程序。C++和c之間的共享內存同步#

程序運行良好,但目前我在定時循環中編寫字符串,並從另一個定時循環中以相同的頻率讀取它。

我想要做的是創建某種鎖定。我想使用信號量/互斥量/任何,所以從C#我無法讀取SHM,而C++程序正在寫它,反之亦然。

我讀過類似命名互斥和semamphore的東西。我可以在兩個程序中創建它們,但我真的不知道如何正確使用它們。

C++程序: MemoryWriter.h

#ifndef MEMORYWRITER_H_ 
#define MEMORYWRITER_H_ 

#include <windows.h> 
#include <string> 
#include <random> 

class MemoryWriter { 

public: 

    MemoryWriter(const std::wstring& name, size_t size); 
    std::string createRandomData() const; 
    void write(const std::string& data); 

private: 

    char getRandomCharacter() const; 
    void createSharedMemory(); 

private: 

    std::wstring m_memoryName; 
    size_t m_memorySize = 0; 
    HANDLE m_shmHandler = 0; 
}; 
#endif // !MEMORYWRITER_H_ 

MemoryWriter.cpp

#include "MemoryWriter.h" 
#include <random> 
#include <iostream> 

/////////////////////////////////////////////////////////////////////////////// 
// USING SECTION                // 
/////////////////////////////////////////////////////////////////////////////// 

using std::string; 

/////////////////////////////////////////////////////////////////////////////// 
// CONSTANTS SECTION               // 
/////////////////////////////////////////////////////////////////////////////// 

const char MinCharacter{ 'A' }; 
const char MaxCharacter{ 'z' }; 

/////////////////////////////////////////////////////////////////////////////// 
// PUBLIC SECTION               // 
/////////////////////////////////////////////////////////////////////////////// 

MemoryWriter::MemoryWriter(const std::wstring& name, size_t size) : 
m_memoryName(name), 
m_memorySize(size) { 
    createSharedMemory(); 
} 

string MemoryWriter::createRandomData() const { 
    string data; 
    for (size_t i = 0; i < m_memorySize; i++) { 
    data += getRandomCharacter(); 
    } 
    return data; 
} 

void MemoryWriter::write(const string& data) { 
    if (!m_shmHandler) { 
    return; 
    } 
    auto buffer = MapViewOfFile(m_shmHandler, FILE_MAP_ALL_ACCESS, 0, 0, m_memorySize); 
    if (NULL == buffer) { 
    std::cerr << "Cannot use MapViewOfFile: null buffer." << std::endl; 
    return; 
    } 
    CopyMemory(buffer, data.c_str(), data.size()); 
} 

////////////////////////////////////////////////////////////////////////////// 
// PRIVATE SECTION               // 
////////////////////////////////////////////////////////////////////////////// 

char MemoryWriter::getRandomCharacter() const { 
    return MinCharacter + rand() % 24; 
} 

void MemoryWriter::createSharedMemory() { 
    m_shmHandler = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, m_memoryName.c_str()); 

    if (!m_shmHandler) { 
    m_shmHandler = CreateFileMapping(
     INVALID_HANDLE_VALUE, 
     NULL, 
     PAGE_READWRITE, 
     0, 
     m_memorySize, 
     m_memoryName.c_str()); 
    } 
} 

的main.cpp

#include "MemoryWriter.h" 
#include <iostream> 
#include <string> 
#include <thread> 

int main(int argc, char* argv[]) 
{ 
    std::wstring memoryName{ L"shm_1" }; 
    size_t memorySize{ 80 }; 
    MemoryWriter writer(memoryName, memorySize); 

    while (true) { 
    std::string data; 
    data = writer.createRandomData(); 
    writer.write(data); 
    std::cout << "C++: Written in shm - " << data << std::endl; 
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
    } 

    return 0; 
} 

C#程序

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace SharedMemoryReader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string shmName = "shm_1"; 
      int shmSize = 80; 
      var shm = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateOrOpen(shmName, shmSize); 
       while (true) 
       { 
        var view = shm.CreateViewStream(); 
        if (view == null) 
        { 
         continue; 
        } 
        byte[] data = new byte[shmSize]; 
        view.Read(data, 0, shmSize); 
        string text = System.Text.Encoding.Default.GetString(data); 
        System.Console.WriteLine("C#: Read from shm - " + text); 
        System.Threading.Thread.Sleep(100); 
       } 
     } 
    } 
} 
+0

在Windows *上搜索並閱讀*命名的信號量。有許多教程和參考可用。 –

回答

1

您將需要一個指定的同步對象。也許是mutex

在C++中,您可以撥打CreateMutex,而在C#中有Mutex類可以爲您處理它。

兩個鏈接都帶有示例,如果遇到特定問題,可以試試並返回。

+0

謝謝我發現了一些關於那個教程.... – Jepessen

1

我會建議使用命名旗語或命名互斥......指定對象是整個系統的

從MSDN Interprocess Synchronization

命名對象的過程提供一種簡單的方法共享對象 句柄