BMC开发九 - D-Bus (2)

发布时间 2023-08-08 14:09:30作者: 球球小世界

消息协议

  • 消息

  消息由头部和消息体组成,如果你把消息当作一个package,那头部就是地址,消息体就是包的内容。消息发送系统使用头部的信息来知道把消息送往何处,如何解释消息,接收者则解释消息体。消息体可以没有或有多个参数,这些参数是具有类型的值,如integer或byte数组。消息头和消息体都使用相同类型的type系统及格式来序列化数据。每种值的类型都有wire格式,从某种别的表示把值转换为wire格式叫作列集(marshalling),而把wire格式转回去则叫散集(unmarshalling).消息头部是有固定签名和意义的值块。消息体是另外的值块,带有在头部中指定的签名。头部必须字节对齐,这样当在一个缓冲区中存贮整个消息时可以允许消息体以8对齐开始。如果头部不是自然地终止于8字节边界上,则必须加上最多7字节的nul初始化的对齐填充。消息体不需要字节对齐。

 

消息有四种类型:METHOD_CALLMETHOD_RETURNERROR, and SIGNAL

   a.METHOD_CALL(方法调用消息)

      这类消息会调用远程对象的操作,这些消息需要映射到对象的方法上去。方法调用消息需要有MEMBER头部域用以指明方法的名称,此消息还可能有一个INTERFACE域来给出接口,被调用的方法也是接口的一部分。在没有INTERFACE域时,如果同一对象上的两个接口有同名的方法名字,哪一个方法会被调用是没有定义的。在这种具有二义性的环境里,实现可以选择返回一个错误。但是,如果方法名是独一无二的,实现不能强制要求需要interface域。还包括一个PATH域,该域用以指明在哪个对象上调用该方法。如果此调用正在消息总线中传播,消息也有一个DESTINATION域用以给出接收此消息的连接名称。当应用程序处理方法调用消息时,它需要答复,答复由REPLY_SERIAL头部域确定 ,此头部域也表明了被答复的方法调用的序列号。答复类型有两种,METHOD_RETURN和ERROR。

   b.METHOD_RETURN &ERROR

      答复消息的参数就是方法调用的返回值或"out parameters",如果答复类型为ERROR,那么会抛出例外,方法调用失败,此时没有返回值提供。对于同一个方法调用发送多个答复是没有意义的。 即使一个方法调用没有返回值,一个METHOD_RETURN的答复也是必须的,这样调用者就能知道方法是否被成功地处理了。

METHOD_RETURN 和ERROR答复消息必须有REPLY_SERIAL头部域。

   d.SIGNAL

          信号发射不象方法调用需要答复。信号发射只是简单单一信息类型SIGNAL。它必须有三个头域,PATH给出发送信号的对象,加上INTERFACE和MEMBER给出信号的全称名字。INTERFACE头部域在信号中是必须的,尽管它在方法调用中是可选的。

  • Bus Name

  可以说是连接的名字,一个连接只有一个总线名字并且是惟一的,在此连接的整个生命周期,这个名字不变。总线名字是STRING类型的,意味着它必须是有效的UTF-8字符串。有两种作用不同的Bus Name,一个叫公共名(well-known names),还有一个叫唯一名(Unique Connection Name)。

  • 对象
    对象是处理消息的一个实例。对象有一个或多个接口,在每个接口有一个或多个的方法,每个方法实现了具体的消息处理。在一对一的通讯中,对象通过一个连接直接和另一个客户端应用程序连接起来。在多对多的通讯中,对象通过一个连接和Dbus守护进程连接起来。对象有一个路径用于指明该对象的存放位置,消息传递时通过该路径找到该对象。
  • 接口
    每个对象都有一个或者多个接口,一个接口就是多个方法和信号的集合。dbus使用简单的命名空间字符串来表示接口,如org.freedesktop.Introspectable。可以说dbus接口相当于C++中的纯虚类。
  • 方法和信号

  每个对象都有一些成员,两种成员:方法(methods)和信号(signals),在对象中,方法可以被调用。信号会被广播,感兴趣的对象可以处理这个信号,同时信号中也可以带有相关的数据。每一个方法或者信号都可以用一个名字来命名,如”Frobate” 或者 “OnClicked”。

  • 对象路径

  一个对象路径是一个用于引用对象实例的名字,从概念上讲,D-Bus信息交换中每个参与者可能有任意数量的对象实例并且每个这样的实例都有一个路径,就象文件系统一样,一个应用中的对象实例形成一个层次树。

  • 服务

  服务是 D-BUS 的最高层次抽象,它们的实现当前还在不断发展变化。应用程序可以通过一个总线来注册一个服务,如果成功,则应用程序就已经 获得 了那个服务。其他应用程序可以检查在总线上是否已经存在一个特定的服务,如果没有可以要求总线启动它。

  • dbus-daemon

  dbus的后台程序(守护进程),libdbus运行时会自动创建dbus-daemon进程。daemon就像一个路由器,将从发送者连接得到的消息转发到由消息中的接收者连接名指定的接收者连接中。

  • 连接

  连接是一个双向的消息传递通道。一个连接将对象和Dbus(dubs-daemon)或客户端应用连接起来,连接支持非阻塞式的异步消息发送和阻塞式的同步消息发送。消息通过连接到达目的端后,连接会将挂起在该连接上的进程唤醒,由该进程将消息取走。每个连接都有一个唯一的名字和可选的其他多个名字,用于在多对多通讯时指明消息的发送者和接收者

  • 认证协议(Authentication Protocol)

  消息流开始之前,两个应用之间必须进行认证,简单的纯文本协议用来认证,即SASL档案,相当简单地直接从SASL规范映射过来。没有使用消息编码,只是纯文本信息。