chromium mojo 快速入门

mojo为chromium架构中各个进程内部通信的框架,可作为比较常用的IPC。特点是:速度快依赖少

术语:

消息管道:是一组端点. 每个endpoint有一个接受消息的队列, 在一个端点上写消息会高效地放入对端端点的消息队列上。所以消息管道是双工通信的。

mojom文件:描述了接口,它们描述了类似proto files的强类型消息结构,通过binding generator可以产生对应于不同语言的文件。

给定一个mojom interface和一条message pipe, 它的两个端点可以打上InterfacePtr和Binding的标签。现在它描述了一条这样的message pipe,它发送由mojom interface描述的消息。

InterfacePtr:是发送消息的端点,一旦绑定到一个消息管道的端点,就可以马上序列化要发送的消息,并写入管道

InterfaceRequest:是接受消息的端点,本质上仅仅是一个持有消息管道端点的容器,本身不会做任何事情,需要传递到直到绑定了实现了mojom文件接口的类,才能读取消息。

考虑如下的mojom文件:

module sample.mojom:

interface Logger {
    Log(string message);
}

通过mojo的binding generator可以产生以下的logging.mojom.h的c++文件:

namespace sample {
namespace mojom { 

class Logger {  
  virtual ~Logger() {}   
  virtual void Log(const std::string& message) = 0;
}; 
using LoggerPtr = mojo::InterfacePtr<Logger>;
using LoggerRequest = mojo::InterfaceRequest<Logger>; 
}
}

 

首先需要创建消息管道,通常调用MakeRequest创建:

#include "sample/logger.mojom.h" 
sample::mojom::LoggerPtr logger;
auto request = mojo::MakeRequest(&logger);

MakeRequset的如下:

template <typename Interface>
InterfaceRequest<Interface> MakeRequest(    InterfacePtr<Interface>* ptr,    scoped_refptr<base::SingleThreadTaskRunner> runner = nullptr) {  
  MessagePipe pipe;  
  ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u),            std::move(runner));  
  return InterfaceRequest<Interface>(std::move(pipe.handle1));
}

可见创建消息管道的同时,InterfacePtr端已经绑定到了消息管道的一端,也就是此时,InterfacePtr已经可以向消息管道发送消息了,当然对端还未绑定,发送的消息会堆积在对端。

接下来就需要绑定InterfaceRequest端,即LoggerRequest,一旦绑定,就会安排一个task去读取、反序列化并分化所有可读的消息给mojom文件中接口实现类。例如接口类实现如下:

#include "base/logging.h"
#include "base/macros.h"
#include "sample/logger.mojom.h" 
class LoggerImpl : public sample::mojom::Logger { 
public:  
  // NOTE: A common pattern for interface implementations which have one  
  // instance per client is to take an InterfaceRequest in the constructor.   
  explicit   LoggerImpl(sample::mojom::LoggerRequest request)      : binding_(this, std::move(request)) {}
  ~Logger() override {}   // sample::mojom::Logger:  
  void Log(const std::string& message) override {    
    LOG(ERROR) << \"[Logger] \" << message;  
  }
  
private:  
  mojo::Binding<sample::mojom::Logger> binding_;

  DISALLOW_COPY_AND_ASSIGN(LoggerImpl);
};

此时我们可以使用前面构造的LoggerRequest构造一个LoggerImpl,一但构造完成,消息就会尽可能快地发送给LoggerImpl。最终就可以在实现类的一端看到Logger发送的“hello”。

总的流程可以概括如下:

原文链接:https://blog.csdn.net/tornmy/article/details/82748058