D-Bus 常用接口

本文介绍 D-Bus 应用编程中常用的接口函数,包括总线的连接、信号的发送与接收、远程函数调用和提供函数调用等 API 接口。

连接到总线

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

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

/* 建立和总线的连接 */
DBusConnection *dbus_bus_get (DBusBusType type, DBusError *error);

/* 注册连接名称 */
int dbus_bus_request_name (DBusConnection *connection, const char *name, unsigned int flags, DBusError *error);

/* 关闭连接 */
void dbus_connection_close (DBusConnection *connection);

信号发送与接收

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

进程发出一个信号前,需要创建一个 DBusMessage 对象来代表信号,然后追加上一些需要发出的参数,就可以发向总线了。发完之后需要释放消息对象。信号发送的函数声明如下所示。

/* 创建信号类型消息 */
DBusMessage *dbus_message_new_signal (const char *path, const char *iface, const char *name);

/* 加入参数到信号 */
void dbus_message_iter_init_append (DBusMessage *message, DBusMessageIter *iter);

/* 发送信号到总线 */
dbus_bool_t dbus_connection_send (DBusConnection *connection, DBusMessage *message, dbus_uint32_t *serial);

/* 释放消息 */
void dbus_message_unref (DBusMessage *message);

进程接收信号时,需先告知总线进程感兴趣的消息,然后等待接收消息。信号接收函数声明如下所示。

/* 告知总线感兴趣的消息 */
void dbus_bus_add_match (DBusConnection *connection, const char *rule, DBusError *error);

/* 接收消息 */
DBusMessage * dbus_connection_pop_message (DBusConnection *connection);

/* 判断消息是否为信号 */
dbus_bool_t dbus_message_is_signal (DBusMessage *message, const char *iface, const char *signal_name);

函数调用和提供函数调用

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

/* 创建一个函数调用消息 */
DBusMessage *dbus_message_new_method_call (const char *destination, const char *path, const char *iface,
const char *method);

/* 为消息添加参数 */
void dbus_message_iter_init_append (DBusMessage *message, DBusMessageIter *iter);

/* 发送消息 */
dbus_bool_t dbus_connection_send_with_reply (DBusConnection *connection, DBusMessage *message,
                                             DBusPendingCall **pending_return, int timeout_milliseconds);

/* 阻塞等待返回值 */
void dbus_pending_call_block (DBusPendingCall *pending);

/* 获得返回消息 */
DBusMessage * dbus_pending_call_steal_reply (DBusPendingCall *pending);

/* 获取参数 */
dbus_bool_t dbus_message_iter_init (DBusMessage *message, DBusMessageIter *iter);

提供远程函数调用,首先需告知总线进程感兴趣的消息,其次从总线获取消息并判定消息是方法调用。然后从消息中获取参数进行函数执行,最后创建返回消息,并发送消息至总线,由总线转发至调用的进程。函数声明如下所示。

/* 请求获取调用消息 */
void dbus_bus_add_match ( DBusConnection *connection, const char *rule, DBusError *error);

/* 从总线获取消息 */
DBusMessage * dbus_connection_pop_message ( DBusConnection *connection);

/* 判定消息是方法调用 */
dbus_bool_t dbus_message_is_method_call (DBusMessage *message, const char *iface, const char *method);

/* 获取参数 */
dbus_bool_t dbus_message_iter_init (DBusMessage *message, DBusMessageIter *iter);

/* 创建返回消息 */
DBusMessage * dbus_message_new_method_return (DBusMessage *method_call);

/* 在消息中填入参数 */
void dbus_message_iter_init_append ( DBusMessage *message, DBusMessageIter *iter);

/* 发送返回消息 */
dbus_bool_t dbus_connection_send ( DBusConnection *connection,DBusMessage *message, dbus_uint32_t *serial);