我正在尝试使用boost :: interprocess在32位和64位进程之间共享内存。 This bug tracker entry表明这可能在我使用的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
产生了相同的结果。
有没有办法让这项工作?
答案 0 :(得分:1)
我遇到了同样的问题。我有一个DLL在另一个进程内运行,一个控制器应用程序单独编译。我的find()和find_or_construct()会挂起,使它看起来像死锁。改为null_mutex_family什么也没做。
问题原来是用于编译DLL与控制器应用程序的char类型。将两者设置为使用多字节字符为我修复它(使用MSVC)。
我将这一行添加到我的代码中,以便在访问我的managed_shared_memory实例之前,它永远不会再像我那样咬我。
if (sizeof(char) != 2) throw std::exception("Set your chars right");
如果你尝试使用一种类型的char来查找和构造对象,使用其他类型的应用程序,boost将会无限循环(我没有耐心尝试找到)。
答案 1 :(得分:0)
我在VS2019中使用vc142工具集进行编译的Windows上遇到了相同的问题。我使用了1.73,但我认为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位进程进行对话(反之亦然)。
P.S。另外,请记住,32位平台限制了您可以访问的内存量。根据经验,对于Windows 32位进程,不能获得超过2 GB的共享内存(尽管我对1.5GB没问题,但这取决于许多其他事情)。这意味着,如果您决定在64位进程上分配2 GB或更多空间(这很容易实现),则在32位进程上的段构造函数将获得异常,因为boost(通过Win32 API)将拒绝映射这么大的内存块。