Chrome OS使用D-Bus进行进程间通信。 在一个高层,D-Bus由一个由dbus-daemon进程管理的系统总线组成。 客户端(通常是系统守护程序或Chrome)通过/run/dbus/system_bus_socket连接到系统总线,并使用它来相互通信。
本文档介绍了在Chrome OS系统守护程序中使用D-Bus的最佳实践。 有关在Chrome中使用D-Bus的详细信息,请参阅Chrome中的D-Bus使用情况文档。
使用Chrome的D-Bus绑定。
自2013年以来,Chrome的C ++ D-Bus绑定已作为libchrome软件包的一部分在Chrome OS上提供(特别是在libbase-dbus共享库中)。这些绑定与Chrome的消息循环和回调类紧密集成,并遵循我们的样式指南和C ++最佳实践。编写它们是为了避免在较旧的Chrome OS代码中经常遇到的常见陷阱(例如,混合服务名称和路径,无法回复方法调用等)。所有新的C ++代码都应该使用Chrome的绑定。
libbrillo(以前称为libchromeos)提供了基于libchrome绑定构建的附加代码,以及可以减少重复设置代码的DBusDaemon和DBusServiceDaemon类。它可能在已经使用libbrillo中的其他代码的守护进程中很有用。 chromeos-dbus-bindings(也称为dbus-bindings-generator)也可用于为基于libbrillo的D-Bus守护进程生成自定义绑定。
某些较旧的Chrome操作系统代码使用其他D-Bus绑定:
libdbus,低级D-Bus C API:Chrome的绑定建立在这个库之上,但你不应该直接使用它。它需要仔细的内存管理,不能很好地与C ++集成,并且容易出错。正如图书馆自己的文档所说,“如果你直接使用这个低级别的API,你就会注册一些痛苦。”
dbus-glib:GLib使用微妙的ref / unref语义实现自己的对象系统,并期望使用自己的消息循环。使用它的代码容易出现内存泄漏和免费使用后的错误,并且它无法轻松与Chrome的消息循环集成。
dbus-c ++:这个库没有维护。它大量使用异常(Chrome C ++代码中禁止使用),并且不能与我们的其他代码很好地集成。
避免将这些绑定用于新代码,并考虑更新现有代码以使用Chrome的绑定(就像session_manager,shill,power_manager等所做的那样)。
熟悉核心D-Bus概念。
D-Bus通信由消息组成,消息通常是方法调用或信号。 方法调用是从一个进程到另一个进程的请求,该请求生成回复(有时也称为响应)或错误。 信号是来自一个进程的异步广播,可以由多个进程接收。 两者都可能有相关的参数,可以使用dbus::MessageWriter或dbus::MessageReader类编写或读取
当进程连接到dbus-daemon时,会为其分配唯一的连接名称。 唯一的连接名称类似于IP地址。 此名称将以冒号开头,例如:1.25。 使用dbus::Bus建立连接。
连接到D-Bus后,进程可以另外请求一个well-known names(有时也称为Chrome OS代码库中的服务名称)。 well-known names类似于主机名,并允许进程相互查找。 按照惯例,这些采用org.chromium.ProgramName形式。 使用dbus::Bus::RequestOwnership()或dbus::Bus::RequestOwnershipAndBlock()请求well-known域名的所有权。
要接收方法调用,程序通常会注册对象路径(有时也称为Chrome OS代码库中的服务路径)。 对象路径采用/org/chromium/ProgramName形式。 当前进程拥有的D-Bus对象由dbus::ExportedObject表示,并使用dbus::Bus::GetExportedObject()注册。 要获取可用于
call methods 或从远程服务导出的对象注册
signals的对象代理,请将服务名称和路径传递给dbus::Bus::GetObjectProxy()。
命名的方法和信号组称为接口。 接口名称看起来类似于well-known names,例如org.chromium.ProgramNameInterface。
使用方法调用请求。 使用信号进行通知。
方法是可以在对象上调用的操作,具有可选输入(也称为参数或“参数”)和输出(也称为返回值或“输出参数”)。 信号是从对象广播到对象的任何感兴趣的观察者; 信号可以包含数据有效载荷。
使用方法调用(请参阅dbus::MethodCall,dbus::ExportedObject::ExportMethod()和dbus::ObjectProxy::CallMethod*())将请求发送到另一个D-Bus客户端。 方法调用触发器回复:将发送错误来报告失败,并在成功时返回(可能为空)回复。
通过方法调用发出的请求示例:
指示电源管理器关闭系统。
指示Chrome锁定屏幕。
询问会话管理器用户当前是否已登录。
使用信号(请参阅dbus::Signal,dbus::ExportedObject::SendSignal()和dbus::ObjectProxy::ConnectToSignal())把状态变更广播给其