Message Passing System
GNURadio的最初设计是为了处理数据流,比特和采样点为基本的处理单位。为了传输控制信息,元数据,包结构,Gnuradio引入了标签流。标签流和数据流是并行处理的。这个模型使得模块可以识别一些特殊的事件,采取一定的措施。
缺点是:标签流只能单向流动,而且只能在模块的work函数访问。优点是,标签流和数据流是等同步的。
设计这个机制的两个目的是:
- 下行的模块可以回传数据给上行模块
- 外部程序可以用这个接口和GNURADIO通信
这个模块严重依赖多态类型实现(PMT)。
这个机制的接口是独立于数据流的,所以创建模块的时候不需要
API
message__port是嵌入到basic_block类中的,所有block都继承了这个部分。
- 注册新端口
void message_port_register_in(pmt::pmt_t port_id)
void message_port_register_out(pmt::pmt_t port_id)
- 端口发布信息
void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg);
在模块内部,发布消息的时候,会遍历所有绑定的端口,调用_post发布消息。
void gr::basic_block::_post(pmt::pmt_t which_port, pmt::pmt_t msg)
- 绑定端口,接受信息
void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target);
void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target);
- 处理接受的消息
set_msg_handler(pmt::pmt_t port_id, boost::bind(&block_class::message_handler_function, this, _1));
这里使用了C++ boost库的bind函数。
例子
- 在流程图中连接:
self.tb.msg_connect(src, "pdus", dbg, "print")
port_id直接使用了string,这也是可以的。
- gr::blocks::message_debug
这是GNURADIO内嵌的一个使用message机制的模块。pmt::mp构造了pmt对象。
message_debug_impl::message_debug_impl()
: block("message_debug",
io_signature::make(0, 0, 0),
io_signature::make(0, 0, 0))
{
message_port_register_in(pmt::mp("print"));
set_msg_handler(pmt::mp("print"), boost::bind(&message_debug_impl::print, this, _1));
message_port_register_in(pmt::mp("store"));
set_msg_handler(pmt::mp("store"), boost::bind(&message_debug_impl::store, this, _1));
message_port_register_in(pmt::mp("print_pdu"));
set_msg_handler(pmt::mp("print_pdu"), boost::bind(&message_debug_impl::print_pdu, this, _1));
}
set_msg_handler绑定了处理函数print,store,print_pdu。其中print的实现如下。
void
message_debug_impl::print(pmt::pmt_t msg)
{
std::cout << "***** MESSAGE DEBUG PRINT ********\n";
pmt::print(msg);
std::cout << "**********************************\n";
}
- 外部向内部传递数据
port = pmt.intern("pdus")
msg = pmt.cons(pmt.PMT_NIL, pmt.make_u8vector(16, 0xFF))
src.to_basic_block()._post(port, msg)