简体   繁体   English

boost::interprocess 32 和 64 位进程之间的共享内存

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

I'm trying to get boost::interprocess to share memory between 32 bit and 64 bit processes.我试图让 boost::interprocess 在 32 位和 64 位进程之间共享内存。 This bug tracker entry suggests that this might be possible in Boost 1.49, which is what I use.这个错误跟踪器条目表明这在我使用的 Boost 1.49 中可能是可能的。

As a test I tried sharing an unsigned int.作为测试,我尝试共享一个 unsigned int。 It's a simple Qt application with two buttons.这是一个带有两个按钮的简单 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;
  }
}

If I create or access the shared memory from processes with the same bitness it works without problems.如果我从具有相同位数的进程创建或访问共享内存,它可以毫无问题地工作。 But if I create the memory in a 64 bit process, and read from a 32 bit process, the process enters the managed_shared_memory::find() function and never comes back.但是如果我在 64 位进程中创建内存,并从 32 位进程读取,该进程进入managed_shared_memory::find()函数并且永远不会回来。 If I try it the other way round, the 64 bit process fails in managed_shared_memory::find() again, this time with an access violation.如果我反过来尝试,64 位进程再次在managed_shared_memory::find()中失败,这次是访问冲突。 Using managed_windows_shared_memory yielded the same results.使用managed_windows_shared_memory产生相同的结果。

Is there any way to make this work?有什么办法可以使这项工作?

I had the same problem.我有同样的问题。 I had a DLL running inside another process and a controller app compiled separately.我在另一个进程中运行了一个 DLL,并单独编译了一个控制器应用程序。 My find() and find_or_construct() would hang, making it look like a dead lock.我的 find() 和 find_or_construct() 会挂起,使它看起来像一个死锁。 Changing to null_mutex_family did nothing.更改为 null_mutex_family 什么也没做。

The problem turned out to be the char type used to compile the DLL vs. the controller app.问题原来是用于编译 DLL 与控制器应用程序的字符类型。 Setting both to use Multi-Byte chars fixed it for me (using MSVC).将两者都设置为使用多字节字符为我修复了它(使用 MSVC)。

I added this line to my code so that it will never, ever bite me like that again, right before accessing my managed_shared_memory instance.我将这一行添加到我的代码中,以便它永远不会在访问我的 managed_shared_memory 实例之前再次像那样咬我。

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

If you try to find and object constructed with one type of char, from an app using another type, boost will hang in an endless loop (that I have not had the patience to try and find).如果您尝试从使用另一种类型的应用程序中查找和使用一种类型的字符构造的对象,boost 将陷入无限循环(我没有耐心尝试找到)。

I had the same issue on Windows, compiling with vc142 toolset, in VS2019.我在 Windows 上遇到了同样的问题,在 VS2019 中使用 vc142 工具集进行编译。 I used boost 1.73, but I think boost 1.60+ will work, too.我使用了 boost 1.73,但我认为 boost 1.60+ 也可以。 Also, I was using Windows managed memory, as opposed to the regular managed memory the original questioner was using.此外,我使用的是 Windows 托管内存,而不是原始提问者使用的常规托管内存。 But I think that my solution still applies.但我认为我的解决方案仍然适用。

I was able to resolve it, after I noticed that, while compiling在我注意到这一点之后,我能够解决它,同时编译

    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.

On my 32-bit platform it was, effectively, invoking this constructor:在我的 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);

Whereas on the 64-bit platform:而在 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);

As you can see, the offset_ptr's template parameters are different, between the two.如您所见,offset_ptr 的模板参数在两者之间是不同的。 This results in somewhat different binary layout assumptions between 32-bit and 64-bit processes, which further leads to issues utilizing the shared memory.这导致 32 位和 64 位进程之间的二进制布局假设有些不同,这进一步导致了使用共享内存的问题。

All you need to do is to make your managed segment type fully identical across the platforms.您需要做的就是使您的托管细分市场类型在各个平台上完全相同。 So, my solution was simple -- just list the template parameters explicitly and compatibly with the 64-bit platform:所以,我的解决方案很简单——只需明确列出与 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!

After that, I was able to have my 32-bit process talk with my 64-bit process via the shared mem segment (and vice versa).之后,我可以通过共享内存段让我的 32 位进程与我的 64 位进程对话(反之亦然)。

PS Also, keep in mind that the 32-bit platform is limiting you in how much memory you can access. PS 另外,请记住,32 位平台限制了您可以访问的内存量。 You cannot, as a rule of thumb get more than 2 GB (I had no problem with 1.5GB though, but it depends on many other things) of shared mem, for a Windows 32-bit process.根据经验,对于 Windows 32 位进程,您不能获得超过 2 GB(虽然我对 1.5GB 没有问题,但这取决于许多其他事情)的共享内存。 Which means that if you decided to allocate 2 GB or more on the 64-bit process (which is easily doable), your segment constructor on the 32-bit process will get an exception, because boost (via Win32 API) will refuse to map that big of a memory chunk.这意味着,如果您决定在 64 位进程上分配 2 GB 或更多内存(这很容易实现),您在 32 位进程上的段构造函数将出现异常,因为 boost(通过 Win32 API)将拒绝映射这么大的内存块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM