我正在尝试为Boost Interprocess message_queue
设计一个好的命名方案。假设有一组进程都使用同一队列。这组过程可能同时存在多个“运行”。我假设每次运行都需要在进程组中使用的每个队列使用唯一的名称。以下原型代码将一堆消息发送到服务器进程,该服务器进程从队列中读取消息,然后打印它们:
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/serialization/string.hpp>
#include <iostream>
#include <vector>
#include <unistd.h>
namespace ipc = boost::interprocess;
constexpr unsigned messages{1000000};
constexpr unsigned maxMessageSize{8192};
struct Message
{
std::string prefix;
template<typename Archive>
void serialize(Archive& ar, const unsigned int)
{
// clang-format off
ar & prefix;
// clang-format on
}
};
int loggerServerMain()
{
try
{
// Open a message queue.
ipc::message_queue mq(ipc::open_only, "message_queue");
unsigned int priority;
ipc::message_queue::size_type recvd_size;
for (int i = 0; i < messages; ++i)
{
std::string data;
data.resize(maxMessageSize);
mq.receive(&data[0], maxMessageSize, recvd_size, priority);
if (recvd_size > maxMessageSize)
return 1;
std::istringstream iss{data};
boost::archive::binary_iarchive ia{iss};
Message message;
ia >> message;
std::cout << message.prefix << '\n';
}
}
catch (const ipc::interprocess_exception& ex)
{
std::cout << ex.what() << std::endl;
return 1;
}
ipc::message_queue::remove("message_queue");
return 0;
}
int main()
{
try
{
ipc::message_queue::remove("message_queue");
ipc::message_queue mq(ipc::create_only, "message_queue", 100, maxMessageSize);
if (fork() == 0)
{
exit(loggerServerMain());
}
for (int i = 0; i < messages; ++i)
{
Message message{"lib" + std::to_string(i)};
std::ostringstream oss;
boost::archive::binary_oarchive oa{oss};
oa << message;
std::string data{oss.str()};
mq.send(data.data(), data.size(), 0);
}
}
catch (const ipc::interprocess_exception& ex)
{
std::cout << ex.what() << std::endl;
return 1;
}
return 0;
}
因此,我们有一个过程可以派生一台服务器,然后继续将一堆消息发送到服务器,该服务器随后将打印消息。我们将硬编码名称“ message_queue”用作基础消息队列的名称。
我很惊讶地发现,当同时启动此过程的多个实例时,该示例仍然可以工作,例如:
./message_queue > 1.log & ; sleep 1 ; ./message_queue > 2.log
两个日志均以正确的顺序包含所有消息。 message_queue
的第一个实例在第二个实例启动时仍在运行。这两个日志都是同时创建和写入的。
当同时从多个进程“组”中使用时,怎么可能没有消息队列争用?我假设消息队列的名称是在系统级别定义的一些全局名称,但是从我的示例看来,它是以某种方式在每个进程树中定义的?我浏览了Boost Interprocess的文档,但是找不到任何提及。
我正在使用Linux 4.20,GCC 8.1.0。示例代码编译如下:
g++ -std=c++17 -O3 -o message_queue message_queue.cpp -lpthread -lboost_serialization -lrt