【转载】DBUS及常用接口介绍

转自:https://blog.csdn.net/mr_wangning/article/details/60324291

 

DBUS是一种高级的进程间通信机制。DBUS支持进程间一对一和多对多的对等通信,在多对多的通讯时,需要后台进程的角色去分转消息,当一个进程发消息给另外一个进程时,先发消息到后台进程,再通过后台进程将信息转发到目的进程。DBUS后台进程充当着一个路由器的角色。

    DBUS中主要概念为总线,连接到总线的进程可通过总线接收或传递消息,总线收到消息时,根据不同的消息类型进行不同的处理。DBUS中消息分为四类:

    1.  Methodcall消息:将触发一个函数调用 ;

    2.  Methodreturn消息:触发函数调用返回的结果;

    3.  Error消息:触发的函数调用返回一个异常 ;

    4.  Signal消息:通知,可以看作为事件消息。

1.2  DBUS应用场景

 

    根据DBUS消息类型可知,DBUS提供一种高效的进程间通信机制,主要用于进程间函数调用以及进程间信号广播。

1 . 函数调用

    DBUS可以实现进程间函数调用,进程A发送函数调用的请求(Methodcall消息),经过总线转发至进程B。进程B将应答函数返回值(Method return消息)或者错误消息(Error消息)。

2 . 消息广播

    进程间消息广播(Signal消息)不需要响应,接收方需要向总线注册感兴趣的消息类型,当总线接收到“Signal消息”类型的消息时,会将消息转发至希望接收的进程。

1.3  DBUS通信特点

    DBUS是一种低延迟、低开销、高可用性的进程间通信机制。其协议是二进制的,避免序列化的过程,通信效率较高。DUBUS可以提供一些更高层的功能:

    1.  结构化的名字空间;

    2.  独立于架构的数据格式;

    3.  支持消息中的大部分通用数据元素;

    4.  带有异常处理的通用远程调用接口;

    5.  支持广播类型的通信。
 

2. 技术实现

2.1 实现原理

    DBUS是一种高级的IPC通信机制,通信流程如图 2‑1所示。在DBUS通信过程中,存在一个后台进程(BUS Daemon Process)。后台进程和普通进程间信息交互是通过域套接字进行通信。

 
图 2-1 DBUS通信原理

     如图 2‑1所示,进程1(Process1)需先连接到总线(dbus_bus_get),其次构造消息(dbus_message_new_signal),然后发送消息(dbus_connection_send)到后台进程。后台进程接收消息,然后根据消息类型对消息进行不同处理(bus_dispatch_matches)。

     进程2(Process2)接收消息前需要连接到总线,并告知总线自己希望得到的消息类型(dbus_bus_add_match),然后等待接收消息(dbus_connection_pop_message)。进程2(Process2)收到总线转发的消息时会根据消息类型,做不同的处理(若是信号类型则不需要发送返回值给总线)。

2.2 连接到总线

    进程间通信前,需要连接到总线。调用dbus_bus_get函数连接进程到总线,建立进程和总线之间的连接(DBusConnection)。建立连接后,需要为这个连接注册名称,方便后面对这个连接进行操作,调用dbus_bus_request_name函数对连接进行注册名称。

    建立连接和注册名称是在程序开始时执行,程序结束时,调用dbus_connection_close函数关闭一个连接。函数接口声明如程序清单 2‑1所示。

程序清单 2-1 建立、注册名称和关闭连接

 

[plain]  view plain  copy
 
  1. DBusConnection  *dbus_bus_get  (DBusBusType  type,  DBusError   *error)             /*  建立和总线的连接  */  
  2.   
  3. int  dbus_bus_request_name  (DBusConnection   *connection,  
  4.                              const char         *name,  
  5.                              unsigned int        flags,  
  6.                              DBusError        *error)                                   /*  注册连接名称      */  
  7.   
  8. void  dbus_connection_close  (DBusConnection  *connection)                           /*  关闭连接          */  

 

2.3 信号发送与接收

 

2.3.1 信号发送

    DBUS中信号是一种广播的消息,当发出一个信号,所有连接到 DBUS 总线上并注册了接受对应信号的进程,都会收到该信号。

    进程发出一个信号前,需要创建一个 DBusMessage 对象来代表信号,然后追加上一些需要发出的参数,就可以发向总线了。发完之后需要释放消息对象。信号发送的函数声明如程序清单 2‑2所示。
程序清单2-2  信号发送接口
[cpp]  view plain  copy
 
  1. DBusMessage  *dbus_message_new_signal  (const  char  *path,  
  2.                                        const  char  *iface,  
  3.                                        const  char  *name)                       /*  创建信号类型消息      */  
  4.   
  5. void  dbus_message_iter_init_append  ( DBusMessage     *message,  
  6.                            DBusMessageIter  *iter)                /*  加入参数到信号        */  
  7.   
  8. dbus_bool_t  dbus_connection_send  ( DBusConnection  *connection,  
  9.                                      DBusMessage    *message,  
  10.                                      dbus_uint32_t    *serial)                       /*  发送信号到总线        */  
  11.   
  12. void  dbus_message_unref  (DBusMessage *message)                                 /*  释放消息              */  

2.3.2 信号接收

    进程接收信号时,需先告知总线进程感兴趣的消息,然后等待接收消息。信号接收函数声明如程序清单 2‑3所示。
程序清单 2-3 信号接收接口
[cpp]  view plain  copy
 
  1. void  dbus_bus_add_match  ( DBusConnection  *connection,  
  2.                             const char        *rule,  
  3.                             DBusError       *error)                                 /*  告知总线感兴趣的消息   */  
  4.   
  5. DBusMessage  *dbus_connection_pop_message  ( DBusConnection  *connection)         /*  接收消息               */  
  6.   
  7. dbus_bool_t  dbus_message_is_signal  (DBusMessage  *message,  
  8.                                       const char      *iface,  
  9.                                       const char     *signal_name)                    /*  判断消息是否为信号     */  

2.4 函数调用和提供函数调用

2.4.1 函数调用

     调用一个远程函数与发送一个信号原理类似,需要先创建一个消息(DBusMessage),然后通过注册在 DBUS上的名称指定发送的对象。然后追加相应的参数,调用方法分为两种,一种是阻塞式的,另一种为异步调用。异步调用的时候会得到一个“DBusMessage *” 类型的返回消息,从这个返回消息中可以获取一些返回的参数。

    函数调用的函数声明如程序清单 2‑4所示。
程序清单 2-4 函数调用接口
[cpp]  view plain  copy
 
  1. DBusMessage  *dbus_message_new_method_call  (const char  *destination,  
  2.                                              const char  *path,  
  3.                                              const char  *iface,  
  4.                                              const char  *method)                    /*  创建一个函数调用消息    */  
  5.   
  6. void  dbus_message_iter_init_append  (DBusMessage     *message,  
  7.                           DBusMessageIter  *iter)                     /*  为消息添加参数           */  
  8.   
  9. dbus_bool_t  dbus_connection_send_with_reply  (DBusConnection   *connection,  
  10.                                                DBusMessage      *message,   
  11.                                                DBusPendingCall  **pending_return,  
  12.                                                int            timeout_milliseconds)       /*  发送消息                */  
  13.   
  14. void  dbus_pending_call_block  (DBusPendingCall  *pending)                           /*  阻塞等待返回值           */  
  15.   
  16. DBusMessage  *dbus_pending_call_steal_reply  (DBusPendingCall  *pending)             /*  获得返回消息            */  
  17.     
  18. dbus_bool_t  dbus_message_iter_init  (DBusMessage     *message,  
  19.                           DBusMessageIter  *iter)                     /*  获取参数                */  

2.4.2 接收函数调用

    提供远程函数调用,首先需告知总线进程感兴趣的消息,其次从总线获取消息并判定消息是方法调用。然后从消息中获取参数进行函数执行,最后创建返回消息,并发送消息至总线,由总线转发至调用的进程。函数声明如程序清单 2‑5所示。
程序清单 2-5 接收函数调用接口
[cpp]  view plain  copy
 
  1. void  dbus_bus_add_match  ( DBusConnection  *connection,  
  2.                             const char        *rule,  
  3.                             DBusError       *error)                                   /*  请求获取调用消息       */  
  4.    
  5. DBusMessage  *dbus_connection_pop_message  ( DBusConnection  *connection)           /*  从总线获取消息         */  
  6.   
  7. dbus_bool_t  dbus_message_is_method_call (DBusMessage  *message,  
  8.                                           const char     *iface,  
  9.                                           const char     *method)                       /*  判定消息是方法调用     */  
  10.     
  11. dbus_bool_t  dbus_message_iter_init  (DBusMessage     *message,  
  12.                           DBusMessageIter  *iter)                    /*  获取参数               */  
  13.   
  14. DBusMessage  *dbus_message_new_method_return  (DBusMessage *method_call)            /*  创建返回消息           */  
  15.   
  16. void  dbus_message_iter_init_append  ( DBusMessage     *message,  
  17.                            DBusMessageIter  *iter)                   /*  在消息中填入参数       */  
  18.   
  19. dbus_bool_t  dbus_connection_send  ( DBusConnection   *connection,  
  20.                                      DBusMessage     *message,  
  21.                                      dbus_uint32_t     *serial)                        /*  发送返回消息          */  

3. 小结

    DBUS是一种高效、易用的进程间通信方式。本文档介绍了DBUS的通信原理,以信号收发和方法调用为框架,介绍了DBUS中常用的函数接口。

 DBus分为两种类型:system bus(系统总线),用于系统(Linux)和用户程序之间进行通信和消息的传递;session bus(回话总线),用于桌面(GNOME, KDE等)用户程序之间进行通信。

 

4. 参考资料

     网上看到两篇写的很不错的博客,可以参考学习。
      1. http://blog.csdn.net/eastmoon502136/article/details/10044993

      2.http://www.cnblogs.com/liyiwen/archive/2012/12/02/2798876.html

转载于:https://www.cnblogs.com/cxt-janson/p/11428240.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DBus是Linux系统上的一种进程间通信机制,C++中的DBus接口可以用来实现DBus的客户端和服务端。DBus的C++接口主要包括libdbus-c++和dbus-cxx两种,下面分别介绍一下。 1. libdbus-c++ libdbus-c++是DBus的C++封装库,提供了DBus的面向对象的接口,使用起来比较方便。下面是一些常用接口: - DBus::Connection:DBus连接类,用来连接DBus服务总线。 - DBus::Message:DBus消息类,用来构建DBus消息并发送到DBus总线上。 - DBus::ObjectProxy:DBus对象代理类,用来访问DBus服务端的对象。 - DBus::ObjectPath:DBus对象路径类,用来表示DBus对象的路径。 - DBus::Signal:DBus信号类,用来定义DBus信号以及监听DBus信号。 - DBus::MethodProxy:DBus方法代理类,用来调用DBus服务端的方法。 其中,DBus::Connection和DBus::ObjectProxy是使用最频繁的类,下面是它们的使用示例: ```cpp #include <dbus-c++/dbus.h> #include <iostream> int main() { DBus::init(); DBus::Connection conn = DBus::Connection::SessionBus(); if (!conn.is_connected()) { std::cerr << "Failed to connect to the D-BUS session bus.\n"; return 1; } DBus::ObjectProxy proxy = conn.get_object("com.example.ExampleService", "/com/example/ExampleObject"); DBus::MethodProxy method = proxy.get_method("ExampleMethod"); method(); return 0; } ``` 上面的代码首先调用DBus::init()进行初始化,然后创建一个DBus::Connection对象,连接到DBus服务总线。接着,创建一个DBus::ObjectProxy对象,指定要访问的DBus对象路径,再创建一个DBus::MethodProxy对象,指定要调用的DBus方法名,最后调用method()方法即可调用DBus方法。 2. dbus-cxx dbus-cxx是另一个DBus的C++封装库,与libdbus-c++相比,dbus-cxx更加轻量级,使用起来也更加灵活。下面是一个简单的dbus-cxx的示例: ```cpp #include <dbus-cxx.h> #include <iostream> void on_signal(const std::string& message) { std::cout << "Signal received: " << message << std::endl; } int main() { DBus::init(); DBus::Connection conn = DBus::Connection::SessionBus(); if (!conn.is_connected()) { std::cerr << "Failed to connect to the D-BUS session bus.\n"; return 1; } DBus::ObjectProxy proxy = conn.get_object("com.example.ExampleService", "/com/example/ExampleObject"); DBus::Signal signal = proxy.get_signal("ExampleSignal"); signal.connect(on_signal); return 0; } ``` 上面的代码首先调用DBus::init()进行初始化,然后创建一个DBus::Connection对象,连接到DBus服务总线。接着,创建一个DBus::ObjectProxy对象,指定要访问的DBus对象路径,再创建一个DBus::Signal对象,指定要监听的DBus信号名,并通过connect()方法注册一个回调函数,当DBus信号被触发时,会调用该回调函数。 总的来说,DBus的C++接口比较复杂,如果要使用DBus进行进程间通信,建议先了解DBus的基本概念和使用方法,再进行开发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值