共享内存
共享内存通常是interprocess 通信的最快的方式。它提供了一个在进程process之间共享的内存区域。一个process可以将数据写入该区域,另一个process可以读取它。
在boost.interprocess中,该类boost::interprocess::shared_memory_object用于表示共享内存。包含头文件boost/interprocess/shared_memory_object.hpp以使用此类。
示例. 创建共享内存
#include
#include
using namespace boost::interprocess;
int main()
{
shared_memory_object shdmem{open_or_create, "Boost", read_write};
shdmem.truncate(1024);
std::cout << shdmem.get_name() << '\n';
offset_t size;
if (shdmem.get_size(size))
std::cout << size << '\n';
}
boost::interprocess::shared_memory_object通过三个参数使用构造函数。
第一个参数指定应创建还是仅仅是打开共享内存。示例包含了这两种情况,也就是说boost::interprocess::open_or_create:如果已经存在共享内存则打开共享内存,如果不存在共享内存创建共享内存。打开共享内存说明该共享内存是之前创建的。
要唯一识别共享内存,请分配一个名称。
第二个参数指定boost::interprocess::shared_memory_object的名字。
第三个参数说明进程如何访问共享内存。在示例33.1中boost::interprocess::read_write:说明该进程对共享内存具有读写访问权限。
创建boost::interprocess::shared_memory_object类型对象后,操作系统中将存在相应的共享内存块。该内存区域的大小最初为0。要使用该区域,调用truncate(),传递参数明白了共享内存的大小(以字节为单位)。在示例中,共享内存提供了1,024个字节空间。truncate()只有在以boost::interprocess::read_write方式打开共享内存的情况下才能调用。如果没有,则抛出了异常:boost::interprocess::interprocess_exception。truncate()可以重复调用以调整共享内存的大小。
创建共享内存后,成员函数get_name()和get_size()可以用来查询共享内存的名称和大小。
由于共享内存用于在不同进程之间交换数据,因此每个进程都需要将共享存储器映射到其地址空间中。类boost::interprocess::mapped_region用于执行此操作。即访问共享内存需要两个(boost::interprocess::shared_memory_object和boost::interprocess::mapped_region)。这样做是为了使类boost::interprocess::mapped_region也可以用于将其他对象映射到进程的地址空间中。
示例. 将共享内存映射到进程的地址空间
#include
#include
#include
using namespace boost::interprocess;
int main()
{
shared_memory_object shdmem{open_or_create, "Boost", read_write};
shdmem.truncate(1024);
mapped_region region{shdmem, read_write};
std::cout << std::hex << region.get_address() << '\n';
std::cout << std::dec << region.get_size() << '\n';
mapped_region region2{shdmem, read_only};
std::cout << std::hex << region2.get_address() << '\n';
std::cout << std::dec << region2.get_size() << '\n';
}
要使用类boost::interprocess::mapped_region,请包括标头文件boost/interprocess/mapped_region.hpp。
boost::interprocess::mapped_region类的构造函数的第一个参数是boost::interprocess::shared_memory_object类的对象;第二个参数确定对内存区域的访问是仅读取还是读写。
示例. 创建了两个类型为 boost::interprocess::mapped_region的对象。名为Boost的共享内存被映射到进程的地址空间。mapped_region成员函数get_address()和get_size()获取映射的内存区域的地址和大小。get_size()在两种情况下返回1024,但是get_address()返回值不同。
示例. 在共享内存中写入和读取
#include
#include
#include
using namespace boost::interprocess;
int main()
{
shared_memory_object shdmem{open_or_create, "Boost", read_write};
shdmem.truncate(1024);
mapped_region region{shdmem, read_write};
int *i1 = static_cast<int*>(region.get_address());
*i1 = 99;
mapped_region region2{shdmem, read_only};
int *i2 = static_cast<int*>(region2.get_address());
std::cout << *i2 << '\n';
}
示例使用映射的内存区域写和读取一个数字。region将数字99写入共享内存的开头。然后,region2在共享内存中读取相同的位置,并将数字写入标准输出流。即使region和region2表示进程中的不同内存区域,如上一个示例中的get_address()返回值所示,该程序也会打印99,因为两个内存区域都可以访问相同的基础共享内存。
示例. 删除共享内存
#include
#include
using namespace boost::interprocess;
int main()
{
bool removed = shared_memory_object::remove("Boost");
std::cout << std::boolalpha << removed << '\n';
}
要删除共享内存,boost::interprocess::shared_memory_object提供静态成员函数remove(),该函数以要删除的共享内存的名称为参数。
如果remove()从未调用,即使程序终止,共享内存也会继续存在。共享内存是否自动删除取决于基础操作系统。一旦重新启动系统,Windows和许多UNIX操作系统(包括Linux)将自动删除共享内存。
Windows提供了一种特殊的共享内存,一旦使用它的最后一个进程终止,该内存将自动删除。可以在boost/interprocess/windows_shared_memory.hpp访问boost::interprocess::windows_shared_memory类,使用这种共享内存。
示例. 使用特定于Windows的共享内存
#include
#include
#include
using namespace boost::interprocess;
int main()
{
windows_shared_memory shdmem{open_or_create, "Boost", read_write, 1024};
mapped_region region{shdmem, read_write};
int *i1 = static_cast<int*>(region.get_address());
*i1 = 99;
mapped_region region2{shdmem, read_only};
int *i2 = static_cast<int*>(region2.get_address());
std::cout << *i2 << '\n';
}
boost::interprocess::windows_shared_memory不提供成员函数truncate()。相反,需要将共享内存的大小作为第四个参数传递给这个类的构造函数。
类boost::interprocess::windows_shared_memory只能在Windows上使用,不可移植。