Dbus客户端使用指南


Dbus是Linux使用的进程间通信机制,允许各个进程互相访问,而不需要为每个其他组件实现自定义代码.即使对于系统管理员来说,这也是一个相当深奥的主题,但它确实有助于解释Linux的另一部分是如何工作的.
这里主要介绍 dbus-sendGDbus CLI工具,其他的还有 QtDbus .
命令行工具 d-feet是フリーデスクトップ提供的Dbus包配套的命令客户端工具,可用于发送Dbus消息.dbus-send实现的Dbus工具.较与 GDbus拥有更完整的功能.dbus-send可以处理所有Dバス服务的GUI应用程序.

Dbus送信


Dbus有两种消息总线 (d-feet)message bussystem bus通过使用 session bus--system选项来通过 --session向系统总线或会话总线发送消息.如果两者都未指定,默认为*セッションバス.
借此,顺道聊下 dbus-sendsystem bus
  • session bus
  • 在桌面上,为所有用户提供一条总线.
  • 专用于系统服务.
  • 有关于低级时间,例如 网络连接,USB设备.
  • - 在嵌入式Linux系统中,システムバス是唯一Dバス类型。


  • System Bus
  • 每个用户会话一个实例
  • 为用户应用提供那个桌面服务.
  • 连接到 Session Bus
  • 参数选项

    X-session这个是必选的参数,指定要接收消息的接口名称.例如 --dest=NAME .org.freedesktop.ExampleName打印回复消息.--print-reply如选项一样,打印回复正文.如有特殊字符,如对象或 オブジェクト则按字面打印,没有标点符号、转义字符等.--print-reply=literal可选参数,等待回复的超时时长,单位为 毫秒.--reply-timeout=发送的消息是システムバス还是セッションバス默认为 セッションバス.--system|--session调用的方法:默认为シグナル
    必须始终指定要发送的消息的对象路径和名称.以下参数(如果有)是消息内容(消息参数).这些值作为类型指定的值给出,可能包括如下所述的容器(数组、判決和变体).

    支持参数

    --type=method_call|signal发送的消息,在调用方法需要传参数时,必须将这些值给出. dbus-send支持传入的参数的类型,并不为Dバス支持的所有的数据类型,仅为一些简单的类型:如
  • タイプ:这里 dbus-send仅仅为简单的数据类型,即 type支持的内容如下: type:content .
  • 数组: string | int16 | uint16 | int32 | uint32 | int64 | uint64 | double | byte | boolean | objpath
  • 词典: array = array:<type>:<value>[,<value>...] .
  • 变体: dict = dict:<type>:<type>:<key>,<value>[,<key>,<value>...] .
  • 根据官网的解析出来后如上述集中数据类型,更详细的描述可以根据官方 dbus-send进行参考.
    可以通过一张图来理解 variant = variant:<type>:<value>发送一个消息所需的几个必须参数

    通过简单的命令,来了解一个 dbus-send命令如何传入参数
     dbus-send --dest=org.freedesktop.ExampleName \  # service
       /org/freedesktop/sample/object/name \  # object
       org.freedesktop.ExampleInterface.ExampleMethod \ # interface.method
       int32:47 string:'hello world' double:65.32   \ # param int
       array:string:"1st item","next item","last item" \ # param array
       dict:string:int32:"one",1,"two",2,"three",3 \ # param dict
       variant:int32:-8 \ # param variant
       objpath:/org/freedesktop/sample/object/name # param object_path
    

    使用案例


    如列出所有总线接口
    dbus-send --session \
      --dest=org.freedesktop.DBus \
      --type=method_call \
      --print-reply \
      /org/freedesktop/DBus \
      org.freedesktop.DBus.ListNames
    
    查看对方总线所支持的对象接口, dbus-send Eye org.freedesktop.DBus.Introspectableorg.freedesktop.DBus.Properties .每个接口实现一些方法和信号.这些是你可以与之互动的东西.
    dbus-send --session \
        --type=method_call \
        --print-reply \
        --dest=org.freedesktop.DBus \ 
        / \
        org.freedesktop.DBus.Introspectable.Introspect
    
    org.freedesktop.PowerManagement也支持调用远程总线接口,通过默认通过 dbus-sendDBUS_SESSION_BUS_ADDRESS来指定远程的总线.
    DBUS_SESSION_BUS_ADDRESS=""
    dbus-send --session \
        --type=method_call \
        --print-reply \
        --dest=org.freedesktop.DBus \ 
        / \
        org.freedesktop.DBus.Introspectable.Introspect
    

    Gdbus


    Gdbus是 グライダー实现的Dbus工具.较与 DBUS_SYSTEM_BUS_ADDRESS拥有更完整的功能.dbus-send可以打印出对象的接口和属性值.对应对象的所有者需要实现 introspect的接口.使用 org.freedesktop.DBus.Introspectable选项,将打印返回的 --xml格式. xml选项可将其子级等打印, --recurse选项仅打印具有属性的接口.--only类似于 monitordbus-monitor调用一个方法,传入的必须为 call而相应的也为 GVariant .GVariant发出信号.信号中包含的每个参数除字符串外都必须序列化为gvariant .
    使用案例
    gdbus introspect --system \
        --dest org.freedesktop.UPower \
        --object-path \
        / \
        --recurse  \
        --only-properties 
    
    通过呼び出し来向一个Dbusサービス发送信息
    gdbus call --session \
                 --dest org.freedesktop.Notifications \
                 --object-path /org/freedesktop/Notifications \
                 --method org.freedesktop.Notifications.Notify \
                 my_app_name \
                 42 \
                 gtk-dialog-info \
                 "The Summary" \
                 "Here's the body of the notification" \
                 [] \
                 {} \
                 5000
    (uint32 12,)
    
    监听一个服务的对象
    gdbus monitor \
        --system \
        --dest org.freedesktop.NetworkManager \
        --object-path /org/freedesktop/NetworkManager/AccessPoint/4141
    
    发送信号
    gdbus emit --session \
        --object-path /foo \
        --signal org.bar.Foo "['foo', 'bar', 'baz']"
    
    想特定进程发送信号,`--dest 为指定进程.emit
    gdbus emit \
    --session \
    --object-path /bar \
    --signal org.bar.Bar someString \
    --dest :1.42