簡體   English   中英

boost::interprocess 32 和 64 位進程之間的共享內存

[英]boost::interprocess shared memory between 32 and 64 bit processes

我試圖讓 boost::interprocess 在 32 位和 64 位進程之間共享內存。 這個錯誤跟蹤器條目表明這在我使用的 Boost 1.49 中可能是可能的。

作為測試,我嘗試共享一個 unsigned int。 這是一個帶有兩個按鈕的簡單 Qt 應用程序。

#define SHARED_MEMORY_NAME "My shared memory"
#define SHARED_VAR_NAME "testVar"
namespace bip = boost::interprocess;

void on_createMemButton_clicked()
{
  std::cout << "sizeof(unsigned int): " << sizeof(unsigned int) << std::endl;
  bip::shared_memory_object::remove(SHARED_MEMORY_NAME);
  bip::managed_shared_memory mem(bip::create_only, SHARED_MEMORY_NAME, 12345);
  mem.construct<unsigned int>(SHARED_VAR_NAME)(42);
  std::cout << "Created shared memory " << SHARED_MEMORY_NAME << std::endl;
}

void on_accessMemButton_clicked()
{
  try
  {
    std::cout << "sizeof(unsigned int): " << sizeof(unsigned int) << std::endl;
    bip::managed_shared_memory mem(bip::open_only, SHARED_MEMORY_NAME);
    std::pair<unsigned int*, size_t> p = mem.find<unsigned int>(SHARED_VAR_NAME);
    std::cout<< "got " << p.second << " numbers " << std::endl;
    if (p.second > 0)
      std::cout << "first number is: " << *p.first << std::endl;

    bip::shared_memory_object::remove(SHARED_MEMORY_NAME);
  }
  catch (bip::interprocess_exception e)
  {
    std::cout << "Shared mem " << SHARED_MEMORY_NAME << " not found" << std::endl;
  }
}

如果我從具有相同位數的進程創建或訪問共享內存,它可以毫無問題地工作。 但是如果我在 64 位進程中創建內存,並從 32 位進程讀取,該進程進入managed_shared_memory::find()函數並且永遠不會回來。 如果我反過來嘗試,64 位進程再次在managed_shared_memory::find()中失敗,這次是訪問沖突。 使用managed_windows_shared_memory產生相同的結果。

有什么辦法可以使這項工作?

我有同樣的問題。 我在另一個進程中運行了一個 DLL,並單獨編譯了一個控制器應用程序。 我的 find() 和 find_or_construct() 會掛起,使它看起來像一個死鎖。 更改為 null_mutex_family 什么也沒做。

問題原來是用於編譯 DLL 與控制器應用程序的字符類型。 將兩者都設置為使用多字節字符為我修復了它(使用 MSVC)。

我將這一行添加到我的代碼中,以便它永遠不會在訪問我的 managed_shared_memory 實例之前再次像那樣咬我。

if (sizeof(char) != 2) throw std::exception("Set your chars right");

如果您嘗試從使用另一種類型的應用程序中查找和使用一種類型的字符構造的對象,boost 將陷入無限循環(我沒有耐心嘗試找到)。

我在 Windows 上遇到了同樣的問題,在 VS2019 中使用 vc142 工具集進行編譯。 我使用了 boost 1.73,但我認為 boost 1.60+ 也可以。 此外,我使用的是 Windows 托管內存,而不是原始提問者使用的常規托管內存。 但我認為我的解決方案仍然適用。

在我注意到這一點之后,我能夠解決它,同時編譯

    using ManagedShMem = bip::managed_windows_shared_memory;
    ManagedShMem segment(bip::open_or_create, pcShMemName, uiMemSize, 0, perms); // will have issues, if used for crossplatform interaction.

在我的 32 位平台上,它有效地調用了這個構造函數:

    boost::interprocess::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>(boost::interprocess::open_or_create_t __formal, const char * name, unsigned int size, const void * addr, const boost::interprocess::permissions & perm);

而在 64 位平台上:

    boost::interprocess::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0>,0>,boost::interprocess::iset_index>::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0>,0>,boost::interprocess::iset_index>(boost::interprocess::open_or_create_t __formal, const char * name, unsigned __int64 size, const void * addr, const boost::interprocess::permissions & perm);

如您所見,offset_ptr 的模板參數在兩者之間是不同的。 這導致 32 位和 64 位進程之間的二進制布局假設有些不同,這進一步導致了使用共享內存的問題。

您需要做的就是使您的托管細分市場類型在各個平台上完全相同。 所以,我的解決方案很簡單——只需明確列出與 64 位平台兼容的模板參數:

    using ManagedShMem = bip::basic_managed_windows_shared_memory
    <char,
    boost::interprocess::rbtree_best_fit<
        boost::interprocess::mutex_family,
        boost::interprocess::offset_ptr<
            void,
            __int64,
            unsigned __int64,
            0>,
        0>,
    boost::interprocess::iset_index>;
    ManagedShMem segment(bip::open_or_create, pcShMemName, uiMemSize, 0, perms); // now works well on both platforms!

之后,我可以通過共享內存段讓我的 32 位進程與我的 64 位進程對話(反之亦然)。

PS 另外,請記住,32 位平台限制了您可以訪問的內存量。 根據經驗,對於 Windows 32 位進程,您不能獲得超過 2 GB(雖然我對 1.5GB 沒有問題,但這取決於許多其他事情)的共享內存。 這意味着,如果您決定在 64 位進程上分配 2 GB 或更多內存(這很容易實現),您在 32 位進程上的段構造函數將出現異常,因為 boost(通過 Win32 API)將拒絕映射這么大的內存塊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM