主頁 >  其他 > gnu radio學習(三)Message Passing訊息傳遞詳解

gnu radio學習(三)Message Passing訊息傳遞詳解

2021-08-05 08:37:49 其他

Message Passing

  • Introduction(介紹)
  • Message Passing API(訊息傳遞埠)
    • Message Handler Functions(訊息處理函式)
    • Connecting Messages through the Flowgraph(通過流圖連接訊息)
  • Posting from External Sources(從外部來源傳輸)
  • Using Messages as Commands(使用訊息作為命令)
  • Code Examples(代碼樣例)
    • C++
    • Python
  • Flowgraph Example(流圖示例)
    • PDUs
  • Flowgraph Example: Chat Application(流圖樣例:聊天應用)

Introduction(介紹)

GNU Radio was originally a streaming system with no other mechanism to pass data between blocks. Streams of data are a model that work well for samples, bits, etc., but are not really the right mechanism for control data, metadata, or packet structures (at least at some point in the processing chain).
GNU Radio最初是一個流系統,沒有其他機制可以在塊之間傳遞資料,資料流是一種適用于樣本,位等等的一個模型,但是對于控制資料,元資料或者資料包結構來說并不是一個真正正確的機制(至少在傳輸鏈上的一些點來說是這樣)

We solved part of this problem by introducing the tag stream (see Stream Tags). This is a parallel stream to the data streaming. The difference is that tags are designed to hold metadata and control information. Tags are specifically associated with a particular sample in the data stream and flow downstream alongside the data. This model allows other blocks to identify that an event or action has occurred or should occur on a particular item. The major limitation is that the tag stream is really only accessible inside a work function and only flows in one direction. Its benefit is that it is isosynchronous with the data.
我們通過引入標簽流來解決這一部分問題(參考標簽流),這是一個資料流的平行流,不同之處是標簽是被設計用來存放元資料和控制資訊,標簽專門與資料流中的一個特定樣本相關聯并且與資料一起向下流動,這個模型允許其他的塊去識別在一個特定的專案上的一個事件或者動作已經發生或者應該發生,主要的限制是標簽流只能在作業函式的內部被訪問并且只能往一個方向流動,這樣做的好處是它能夠與資料同步,

We want a more general message passing system for a couple of reasons. The first is to allow blocks downstream to communicate back to blocks upstream. The second is to allow an easier way for us to communicate back and forth between external applications and GNU Radio. GNU Radio’s message passing interface handles these cases, although it does so on an asynchronous basis.
出于一些原因,我們想要一個更通用的訊息傳遞系統,首先是要允許下游塊與上游塊通信,其次是允許我們以一種更簡單的方式在外部應用與GNU Radio之間來回通信,GNU Radio的訊息傳遞介面處理這些情況,盡管它是在異步基礎上進行的,

The message passing interface heavily relies on Polymorphic Types (PMTs) in GNU Radio. For further information about these data structures, see the page Polymorphic Types (PMTs).
訊息傳遞介面非常依賴GNU Radio中的多型型別(PMTs),關于這些資料型別的更多介紹可以參考多型型別頁面,

Message Passing API(訊息傳遞埠)

The message passing interface is designed into the gr::basic_block, which is the parent class for all blocks in GNU Radio. Each block has a set of message queues to hold incoming messages and can post messages to the message queues of other blocks. The blocks also distinguish between input and output ports.
訊息傳遞的介面設計在gr::basic_block中,這是GNU Radio中所有塊的父類,每一個塊都有一個訊息佇列來存放輸入的訊息同時還可以傳遞訊息給其他塊的訊息佇列,這些塊還區分輸入和輸出埠,

A block has to declare its input and output message ports in its constructor. The message ports are described by a name, which is in practice a PMT symbol (i.e., an interned string). The API calls to register a new port are:
一個塊需要在它的建構式中宣告它的訊息輸入和輸出埠,訊息埠通過一個名字來描述,這個名字其實是一個PMT符號(例如一個內部字串),注冊新埠的API呼叫如下所示:

 void message_port_register_in(pmt::pmt_t port_id)
 void message_port_register_out(pmt::pmt_t port_id)

In Python:

 self.message_port_register_in(pmt.intern("port name"))
 self.message_port_register_out(pmt.intern("port name"))

The ports are now identifiable by that port name. Other blocks who may want to post or receive messages on a port must subscribe to it. When a block has a message to send, they are published on a particular port using the following API:
現在可以通過埠的名字來區分埠,一個塊想在一個埠上傳輸或者接收資訊就必須得先訂閱它,當一個塊有一個訊息要傳遞,它們將會使用下面的API來發送到一個特定的埠:

 void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg);

In Python:(python實作方式)

 self.message_port_pub(pmt.intern("port name"), <pmt message>)

Subscribing is usually done in the form of connecting message ports as part of the flowgraph, as discussed later. Internally, when message ports are connected, the gr::basic_block::message_port_sub method is called.
訂閱通常以連接訊息埠的形式作為流圖的一部分,稍后在討論,在內部,當訊息埠被連接時,gr::basic_block::message_port_sub方法將被呼叫,

Any block that has a subscription to another block’s output message port will receive the message when it is published. Internally, when a block publishes a message, it simply iterates through all blocks that have subscribed and uses the gr::basic_block::_post method to send the message to that block’s message queue.
任何塊在訂閱了其他塊訊息輸出埠后都將收到它發布的訊息,在內部,當一個塊發布了一個訊息,它只是簡單的遍歷所有訂閱過它的塊并使用gr::basic_block::_post方法來傳遞訊息到那些塊的訊息佇列,

Message Handler Functions(訊息處理函式)

A subscriber block must declare a message handler function to process the messages that are posted to it. After using the gr::basic_block::message_port_register_in to declare a subscriber port, we must then bind this port to the message handler.
訂閱者必須宣告一個訊息處理函式來處理發布給它的訊息,在使用gr::basic_block::message_port_register_in宣告一個訂閱埠后,我們必須將這個埠系結到訊息處理程式上,

Starting in GNU Radio 3.81 using C++11 we do that using a lambda function:
從使用c++11的GNU Radio3.8開始我們開始使用下面的lambda函式

 set_msg_handler(pmt::pmt_t port_id, 
   [this](const pmt::pmt_t& msg) { message_handler_function(msg); });

In Python:

 self.set_msg_handler(pmt.intern("port name"), <msg handler function>)

When a new message is pushed onto a port’s message queue, it is this function that is used to process the message. The ‘port_id’ is the same PMT as used when registering the input port. The ‘block_class::message_handler_function’ is the member function of the class designated to handle messages to this port.
當一個新的訊息被放到一個埠的訊息佇列中后,就是用這個函式來處理訊息的,‘port_id’與注冊輸入埠時使用的PMT相同,‘block_class::message_handler_function’是被指定用來處理埠訊息的類的成員函式,

The prototype for all message handling functions is:
所有訊息處理函式的原型是:

 void block_class::message_handler_function(const pmt::pmt_t& msg);

In Python the equivalent function would be:
python中的函式型別如下:

 def handle_msg(self, msg):

We give examples of using this below.
我們在下面給出了使用它的實體,

Connecting Messages through the Flowgraph(通過流圖連接訊息)

From the flowgraph level, we have instrumented a gr::hier_block2::msg_connect method to make it easy to subscribe blocks to other blocks’ messages. Assume that the block src has an output message port named pdus and the block dbg has an input port named print. The message connection in the flowgraph (in Python) looks like the following:
從流圖層面,我們檢測到一個gr::hier_block2::msg_connect方法使得更容易讓一個塊訂閱其他塊的訊息,假設塊src有一個輸出訊息埠叫做pdus另一個塊dbg有一個輸入埠叫做print,在python中流圖中訊息的傳遞像如下這樣:

  self.tb.msg_connect(src, "pdus", dbg, "print")

All messages published by the src block on port pdus will be received by dbg on port print. Note here how we are just using strings to define the ports, not PMT symbols. This is a convenience to the user to be able to more easily type in the port names (for reference, you can create a PMT symbol in Python using the pmt::intern function as pmt.intern(“string”)).
所有由src塊在pdus埠產生的訊息都會被dbg塊在print埠接收,注意這里我們是如何僅僅通過字串來定義埠,而不是PMT符號,這跟方便用戶更簡單的輸入埠名(提示下,你可以在python中你可以像c++中使用pmt::intern函式一樣使用pmt.inter(”string“)函式來創建一個PMT標簽),

Users can also query blocks for the names of their input and output ports using the following API calls:
用戶 還可以使用以下的API來查詢塊的輸入輸出埠名稱,

   pmt::pmt_t message_ports_in();
   pmt::pmt_t message_ports_out();

The return value for these are a PMT vector filled with PMT symbols, so PMT operators must be used to manipulate them.
它們的回傳值是一個內容為PMT符號的向量組,因此必須使用PMT運算子來操作它們,

Each block has internal methods to handle posting and receiving of messages. The gr::basic_block::_post method takes in a message and places it into its queue. The publishing model uses the gr::basic_block::_post method of the blocks as the way to access the message queue. So the message queue of the right name will have a new message. Posting messages also has the benefit of waking up the block’s thread if it is in a wait state. So if idle, as soon as a message is posted, it will wake up and call the message handler.
每個塊都有一個內部方法來處理發送和接收到的訊息,gr::basic_block::post方法接收一個訊息并把它放入自己訊息佇列中,所以相應的訊息佇列中將會有一個新的訊息,發送訊息同樣有喚醒一個在等待狀態的塊的執行緒,因此,如果在空閑狀態,同時發布一個訊息,那么它將喚醒并調動訊息處理程式,

Posting from External Sources(從外部來源傳輸)

An important feature of the message passing architecture is how it can be used to take in messages from an external source. We can call a block’s gr::basic_block::_post method directly and pass it a message. So any block with an input message port can receive messages from the outside in this way.
訊息傳遞架構的一個重要特點是如何使用它從一個外部的資源中接收訊息,我們可以直接使用塊的gr::basic_block::post方法傳遞訊息,所以任何有訊息輸入埠的塊可以通過這個方法從外部接收到訊息,

The following example uses a gr::blocks::pdu_to_tagged_stream block as the source block to a flowgraph. Its purpose is to wait for messages as PDUs posted to it and convert them to a normal stream. The payload will be sent on as a normal stream while the meta data will be decoded into tags and sent on the tagged stream.
以下示例使用gr::blocks::pdu_to_tagged_stream塊作為流程圖的源塊,它的目的是等待一個訊息作為PDUs發送給它并將它們轉化為普通流,有效載荷將作為一個普通流發送,而元資料將被解碼為標簽并被標記在流上發送,

So if we have created a src block as a PDU to stream, it has a pdus input port, which is how we will inject PDU messages into the flowgraph. These PDUs could come from another block or flowgraph, but here, we will create and insert them by hand.
所以如果我們創建了一個src塊作為流式傳輸的PDU,它有一個pdus輸入埠,這就是我們將PDU訊息注入流程圖的方式,這些PDU可以來自其他塊或者流圖,但是在這里,我們將手動創建并插入它們,

 port = pmt.intern("pdus")
 msg = pmt.cons(pmt.PMT_NIL, pmt.make_u8vector(16, 0xFF))
 src.to_basic_block()._post(port, msg)

The PDU’s metadata section is empty, hence the pmt::PMT_NIL object. The payload is now just a simple vector of 16 bytes of all 1’s. To post the message, we have to access the block’s gr::basic_block class, which we do using the gr::basic_block::to_basic_block method and then call the gr::basic_block::_post method to pass the PDU to the right port.
PDU的元資料部分都是空的,因此是pmt::PMT_NIL物件,有效載荷現在只是一個16位元組的全1向量,要傳遞訊息,我們必須訪問塊的gr::basic_block類,我們使用gr::basic_block::to_basic_block方法同時使用gr::basic_block::_post方法將PDU傳輸到正確的埠,

All of these mechanisms are explored and tested in the QA code of the file qa_pdu.py.
所有的這些機制都在qa_pdu.py檔案中的QA代碼中進行了探索和檢測,

There are some examples of using the message passing infrastructure through GRC in:
這里有一些通過GRC使用訊息傳輸基礎設施的例子:

gr-blocks/examples/msg_passing

Using Messages as Commands(使用訊息作為命令)

One important use of messages is to send commands to blocks. Examples for this include:
一個非常重要的用處是使用訊息向塊傳遞命令,這方面的例子包括:

gr::qtgui::freq_sink_c: The scaling of the frequency axis can be changed by messages(可以通過訊息來改變頻率軸的間隔)

gr::uhd::usrp_source and gr::uhd::usrp_sink: Many transceiver-related settings can be manipulated through command messages, such as frequency, gain and LO offset(許多收發器相關的設定可以通過命令訊息來修改,比如頻率,增益和LO偏移)

gr::digital::header_payload_demux, which receives an acknowledgement from a header parser block on how many payload items there are to process(它從頭決議器接收有多少負載專案要處理的確認)

There is no special PMT type to encode commands, however, it is strongly recommended to use one of the following formats:
沒有特殊的PMT型別來編碼命令,然而,非常建議使用下面的格式:

pmt::cons(KEY, VALUE): This format is useful for commands that take a single value. Think of KEY and VALUE as the argument name and value, respectively. For the case of the QT GUI Frequency Sink, KEY would be “freq” and VALUE would be the new center frequency in Hz.(這個格式非常適用于使用單個值的命令,KEY和VALUE分別為引數名和值,對于QT GUI Frequency Sink案例,KEY將是”freq“而VALUE為新的中心頻率(單位為Hz))

pmt::dict((KEY1: VALUE1), (KEY2: VALUE2), …): This is basically the same as the previous format, but you can provide multiple key/value pairs. This is particularly useful when a single command takes multiple arguments which can’t be broken into multiple command messages (e.g., the USRP blocks might have both a timestamp and a center frequency in a command message, which are closely associated).(這和前面的格式基本一樣,但是你可以使用多個鍵值對,這對一個使用多個引數而不能分解為多個命令訊息的命令非常有用(例如,USRP塊在命令訊息中有時間戳和中心頻率,它們密切相關))

In both cases, all KEYs should be pmt::symbols (i.e. strings). VALUEs can be whatever the block requires.
在這些案例中,所有的KEY都應該是pmt::symbols(即字串),VALUE可以是塊中需要的任何值,

It might be tempting to deviate from this format, e.g. the QT Frequency sink could simply take a float value as a command message, and it would still work fine. However, there are some very good reasons to stick to this format:
偏離這種格式可能很誘人,例如,QT Frequency sink可以簡單的使用浮點數值作為一個訊息命令,它仍然可以正常作業,但是堅持使用這種格式有很多的好處:

Interoperability: The more people use the standard format, the more likely it is that blocks from different sources can work together(使用標準格式的人越多,那么來自不同源的塊能一同作業的機會有越大)

Inspectability: A message debug block will display more useful information about a message if it’s containing both a value and a key(如果一個訊息調式塊包含值和鍵,那么它可以顯示一個訊息的更多的有效資訊)

Intuition: This format is pretty versatile and unlikely to create situations where it is not sufficient (especially considering that values are PMTs themselves). As a counterexample, using positional arguments (something like “the first argument is the frequency, the second the gain”) is easily forgotten, or changed in one place and not another, etc.(這種格式非常通用,不太可能造成一個不適用的情況(特別是考慮到值本身就是PMT),作為一個反例,使用位置引數(比如說”第一個引數是頻率,第二個引數是增益“)非常容易被遺忘, 或者在一個地方而不是另一個地方改變,等等),

Code Examples(代碼樣例)

C++

The following is snippets of code from blocks currently in GNU Radio that take advantage of message passing. We will be using gr::blocks::message_debug and gr::blocks::tagged_stream_to_pdu below to show setting up both input and output message passing capabilities.
以下是當前GNU Radio中利用訊息傳遞的塊的代碼片段,我們將在下面使用gr::blocks::message_debug和gr::blocks::tagged_stream_to_pdu來顯示設定輸入和輸出訊息傳遞功能,

The gr::blocks::message_debug block is used for debugging the message passing system. It describes two input message ports: print and store. The print port simply prints out all messages to standard out while the store port keeps a list of all messages posted to it. The store port works in conjunction with a gr::blocks::message_debug::get_message(size_t i) call that allows us to retrieve message i afterward.
gr::blocks::message_debug塊被用來除錯訊息傳輸系統,它描述了兩個輸入訊息埠:print和store,print埠把所有的訊息簡單的列印到標準輸出,但是store埠存放了被傳輸過來的所有訊息串列,store埠與gr::block::message_debug::get_message(size_t i)一同呼叫,允許我們后面檢索訊息i,

The constructor of this block looks like this:
這個塊的構造如下所示:

 {
   message_port_register_in(pmt::mp("print"));
   set_msg_handler(pmt::mp("print"),
     [this](const pmt::pmt_t& msg) { print(msg); });
 
   message_port_register_in(pmt::mp("store"));
   set_msg_handler(pmt::mp("store"),
     [this](const pmt::pmt_t& msg) { store(msg); });
 }

The three message input ports are registered by their respective names. We then use the gr::basic_block::set_msg_handler function to identify this particular port name with a callback function.
三個訊息輸入埠按照它們各自的名字來注冊,然后,我們使用gr::basic_block::set_msg_handler函式通過回呼函式來識別特定埠的名稱,

So now the functions in the block’s private implementation class, gr::blocks::message_debug_impl::print and gr::blocks::message_debug_impl::store are assigned to handle messages passed to them. Below is the print function for reference.
所以現在塊的私有實作類中的函式gr::blocks::message_debug_impl::print和gr::blocks::message_debug_impl::store函式被用來處理分配給他們的訊息,參考下面的輸出函式,

void
 message_debug_impl::print(const pmt::pmt_t& msg)
 {
   std::cout << "***** MESSAGE DEBUG PRINT ********\n";
   pmt::print(msg);
   std::cout << "**********************************\n";
 }

The function simply takes in the PMT message and prints it. The method pmt::print is a function in the PMT library to print the PMT in a friendly and (mostly) pretty manner.
函式只是簡單的接收了PMT訊息并輸出了他們,PMT庫中的pmt::print方法是一個更友好和漂亮的方式來輸出一個PMT,

The gr::blocks::tagged_stream_to_pdu block only defines a single output message port. In this case, its constructor contains the line:
gr::blocks::tagged_stream_to_pdu塊只是定義了單個的輸出訊息埠,這種情況下,它的建構式包括了一下行:

{
   message_port_register_out(pdu_port_id);
}

So we are only creating a single output port where pdu_port_id is defined in the file pdu.h as pdus.
所以我們只是創建了一個輸出埠,同時pdu_prot_id作為pdus被定義在pdu.h頭檔案里面,

This block’s purpose is to take in a stream of samples along with stream tags and construct a predefined PDU message from it. In GNU Radio, we define a PDU as a PMT pair of (metadata, data). The metadata describes the samples found in the data portion of the pair. Specifically, the metadata can contain the length of the data segment and any other information (sample rate, etc.). The PMT vectors know their own length, so the length value is not actually necessary unless useful for purposes down the line. The metadata is a PMT dictionary while the data segment is a PMT uniform vector of either bytes, floats, or complex values.
塊的目的是接收樣本流和流標簽同時從從它們之中構建一個一個預定義PDU訊息,在GNU Radio中,我們將一個PDU定義為一個PMT對(元資料,資料),元資料描述了在該對資料部分找到的樣本,特別的是,該元資料能夠包含資料段的長度以及任何其他資訊(樣本率等等),PMT向量組知道它們自己的長度,所以長度不是必須的,除非在后面的代碼中有用,元資料是一個PMT資料字典而資料段是位元組、浮點數或者復數值的一個PMT的統一向量,

In the end, when a PDU message is ready, the block calls its gr::blocks::tagged_stream_to_pdu_impl::send_message function that is shown below.
最后,當一個PDU訊息準備好的時候,塊會呼叫它的gr::blocks::tagged_stream_to_pdu_impl::send_message函式,像下面這樣:

 void
 tagged_stream_to_pdu_impl::send_message()
 {
   if(pmt::length(d_pdu_vector) != d_pdu_length) {
     throw std::runtime_error("msg length not correct");
   }
 
   pmt::pmt_t msg = pmt::cons(d_pdu_meta,
                              d_pdu_vector);
   message_port_pub(pdu_port_id, msg);
 
   d_pdu_meta = pmt::PMT_NIL;
   d_pdu_vector = pmt::PMT_NIL;
   d_pdu_length = 0;
   d_pdu_remain = 0;
   d_inpdu = false;
 }

This function does a bit of checking to make sure the PDU is OK as well as some cleanup in the end. But it is the line where the message is published that is important to this discussion. Here, the block posts the PDU message to any subscribers by calling gr::basic_block::message_port_pub publishing method.
此函式會進行一系列的檢查來確保PDU是正確的以及最后的一些清理工作,但是發布訊息的行對于這項作業來說非常重要,在此,塊通過呼叫gr::basic_block::message_port_pub函式的發布方法來向任意它的訂閱者發布訊息,

There is similarly a gr::blocks::pdu_to_tagged_stream block that essentially does the opposite. It acts as a source to a flowgraph and waits for PDU messages to be posted to it on its input port pdus. It extracts the metadata and data and processes them. The metadata dictionary is split up into key:value pairs and stream tags are created out of them. The data is then converted into an output stream of items and passed along. The next section describes how PDUs can be passed into a flowgraph using the gr::blocks::pdu_to_tagged_stream block.
類似的還有一個gr::blocks::pdu_to_tagged_stream塊做了一些本質上相反的事情,它充當一個流圖的源,并等待發送給它的輸入埠pdus的PDU訊息,它提取元資料和資料然后處理它們,元資料字典被拆分為鍵值對并從中創建標簽,然后將資料轉換為一個專案的輸出流并隨后傳遞它們,下一節將描述如何使用gr::blocks::pdu_to_tagged_stream塊將PDUs傳遞到流圖中,

Python

A Python Block example:
一個python塊樣例:

 class msg_block(gr.basic_block):
     def __init__(self):
         gr.basic_block.__init__(
             self,
             name="msg_block",
             in_sig=None,
             out_sig=None)
 
         self.message_port_register_out(pmt.intern('msg_out'))
         self.message_port_register_in(pmt.intern('msg_in'))
         self.set_msg_handler(pmt.intern('msg_in'), self.handle_msg)
 
     def handle_msg(self, msg):
         self.message_port_pub(pmt.intern('msg_out'), pmt.intern('message received!'))

Flowgraph Example(流圖示例)

Here’s a simple example of a flow graph using both streaming and messages:
這里是一個同時使用流和訊息的流圖樣例:

There are several interesting things to point out. First, there are two source blocks, which both output items at regular intervals, one every 1000 and one every 750 milliseconds. Dotted lines denote connected message ports, as opposed to solid lines, which denote connected streaming ports. In the top half of the flow graph, we can see that it is, in fact, possible to switch between message passing and streaming ports, but only if the type of the PMTs matches the type of the streaming ports (in this example, the pink color of the streaming ports denotes bytes, which means the PMT should be a u8vector if we want to stream the same data we sent as PMT).
這里有一些有趣的事情值得被指出,首先,這里有兩個源塊,它們都在一個固定的間隔輸出專案,一個以沒1000毫秒的間隔輸入另一個則以750毫秒的間隔輸入,虛線表示連接訊息埠,而實線表示連接流埠,在流圖的上半部分我們可以看到,實際上,可以實作訊息埠和流埠之間的轉換,但是只有在PMT的型別與流埠相匹配的時候才可以實作(在本樣例中,粉色的流埠表示位元組,意味著如果我們想要以流傳輸我們以PMT形式發送的相同的資料,PMT的格式應該是u8vector的形式),

Another interesting fact is that we can connect more than one message output port to a single message input port, which is not possible with streaming ports. This is due to the asynchronous nature of messages: The receiving block will process all messages whenever it has a chance to do so, and not necessarily in any specific order. Receiving messages from multiple blocks simply means that there might be more messages to process.
另一個有趣的事情是我們可以將多個訊息輸出埠連接到一個訊息輸入埠上,但是這在流埠上是不能實作的,這是由于訊息的異步性:接收塊將在空閑的時間處理所有接收到的訊息,并且不一定要按照一定的順序,從多個塊接收到訊息只是意味著有更多的訊息需要去處理,

What happens to a message once it was posted to a block? This depends on the actual block implementation, but there are two possibilities:
當訊息被發送到一個塊時會發生什么?這取決于塊的實際操作,但是這里有兩種可能性:

  1. A message handler is called, which processes the message immediately.
    1)一個訊息處理器被呼叫,立刻處理訊息,
  2. The message is written to a FIFO buffer, and the block can make use of it whenever it likes, usually in the work function.
    2)訊息被寫入一個FIFO緩沖區,塊可以在任何時候處理它們,這通常在作業函式內實作,

For a block that has both message ports and streaming ports, any of these two options is OK, depending on the application. However, we strongly discourage the processing of messages inside of a work function and instead recommend the use of message handlers. Using messages in the work function encourages us to block in work waiting for a message to arrive. This is bad behavior for a work function, which should never block. If a block depends upon a message to operate, use the message handler concept to receive the message, which may then be used to inform the block’s actions when the work function is called. Only on specially, well-identified occasions should we use method 2 above in a block.
對于一個同時擁有訊息埠 和流埠的塊來說,這兩種選擇都可以,取決于應用程式,當時,我們強烈反對在一個作業函式內來處理訊息,我們推薦通過使用訊息處理器來處理訊息,在作業函式內使用訊息會使得我們在等待訊息的程序中形成阻塞,這對于永遠不能被阻塞的作業函式來說是一個非常不好的行為,如果依賴一個訊息來操作,使用訊息處理程式來接收訊息,然后在呼叫作業函式時來使用訊息來告知塊的操作,只有在啊特殊明確的場合我們才應該使用上面的方法2,

With a message passing interface, we can write blocks that don’t have streaming ports, and then the work function becomes useless, since it’s a function that is designed to work on streaming items. In fact, blocks that don’t have streaming ports usually don’t even have a work function.
通過訊息傳遞介面,我們可以撰寫一個不需要流埠的塊,然后作業函式將變得沒有用,因為作業函式時被設計用來處理流專案的, 事實上,沒有流埠的塊甚至通常沒有作業函式,

PDUs

In the previous flow graph, we have a block called PDU to Tagged Stream. A PDU (protocol data unit) in GNU Radio has a special PMT type, it is a pair of a dictionary (on CAR) and a uniform vector type. So, this would yield a valid PDU, with no metadata and 10 zeros as stream data:
在之前的流圖中,我們有一個叫做PDU to Tagged Stream的塊,一個在GNU Radio中的PDU(協議資料單元)有一個特殊的資料型別,它是一對字典(在CAR上)和統一向量型別,所以我們將會生成一個有效的PDU,沒有元資料和10個0作為流資料,

pdu = pmt.cons(pmt.make_dict(), pmt.make_u8vector(10, 0))

The key/value pairs in the dictionary are then interpreted as key/value pairs of stream tags.
字典中的鍵值對將會解釋為流標簽的鍵值對,

Flowgraph Example: Chat Application(流圖樣例:聊天應用)

Let’s build an application that uses message passing. A chat program is an ideal use case, since it waits for the user to type a message, and then sends it. Because of that, no Throttle block is needed.
讓我們來創建一個傳遞訊息的應用程式,聊天程式是一個非常理想的用例,因為它等待用戶輸入一個訊息,然后發送它,因此它不需要Throttle塊,

Create the following flowgraph and save it as ‘chat_app2.grc’:
創建下面的流圖并保存命名為’chat_app2.grc’:

The ZMQ Message blocks have an Address of ‘tcp://127.0.0.1:50261’. Typing in the QT GUI Message Edit Box will send the text once the Enter key is pressed. Output is on the terminal screen where gnuradio-companion was started.
ZMQ訊息塊有一個地址為’tcp://127.0.0.1:50261’,一但按下回車鍵,QT訊息編輯框中輸入的訊息就會發送出去,輸出在運行gnuradio-companion的終端窗上,

If you want to talk to another user (instead of just yourself), you can create an additional flowgraph with a different name such as ‘chat_app3.grc’. Then change the ZMQ port numbers as follows:
如果你想與另一個用戶(或者就是你自己)交流,你可以創建一個額外的流圖命名為
另一個不同的名字比如’chat_app3.grc’,然后像下面這樣改變ZMQ的埠名:

chat_app2
	ZMQ PUSH Sink: tcp://127.0.0.1:50261
	ZMQ PULL Source: tcp://127.0.0.1:50262
chat_app3
	ZMQ PUSH Sink: tcp://127.0.0.1:50262
	ZMQ PULL Source: tcp://127.0.0.1:50261

When using GRC, doing a Generate and/or Run creates a Python file with the same name as the .grc file. You can execute the Python file without running GRC again.
當使用GRC時,執行生成同時/或者運行命令會創建一個同名.grc檔案的python檔案,你可以在不再次運行GRC的情況下執行python檔案,

For testing this system we will use two processes, so we will need two terminal windows.
我們將使用兩個行程來測驗這個系統,因此我們需要兩個終端視窗,

Terminal 1:(終端1)

since you just finished building the chat_app3 flowgraph, you can just do a Run.
因為我們剛剛完成了chat_app3流圖的構建,因此我們只需要運行即可,

Terminal 2: Open another terminal window.(終端2:打開另一個終端視窗,)

change to whatever directory you used to generate the flowgraph for chat_app2.
更改為你用于為chat_app2生成流圖的任何專案,
execute the following command:
執行以下命令:
python3 -u chat_app2.py

Typing in the Message Edit Box for chat_app2 should be displayed on the Terminal 1 screen (chat_app3) and vice versa.
在chat_app2訊息編輯框中輸入的訊息將會出現在在終端1的螢屏上(chat_app3),反之亦然,

To terminate each of the processes cleanly, click on the ‘X’ in the upper corner of the GUI rather than using Control-C.
要干凈利落的終止整個程式,應該點擊GUI視窗上的’X’關閉而不是輸入Control-C指令,

1 In old GNU Radio 3.7, we used Boost’s ‘bind’ function:
在老版本的GNU Radio 3.7中我們使用了Boost的’bind‘函式:

 set_msg_handler(pmt::pmt_t port_id,
 boost::bind(&block_class::message_handler_function, this, _1));}}

The ‘this’ and ‘_1’ are standard ways of using the Boost bind function to pass the ‘this’ pointer as the first argument to the class (standard OOP practice) and the _1 is an indicator that the function expects 1 additional argument.
’this‘和’_1‘是使用Boost bind函式傳遞第一個’this‘指標引數到類(標準OOP實踐)中以及_1是函式需要一個附加引數的指示符,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291943.html

標籤:其他

上一篇:MQTT(二) 實作聊天功能

下一篇:自行編譯micropython韌體刷入ESP32 cam,并測驗拍照及圖傳

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more