DBus(Desktop Bus)是一种跨进程通信机制,提供了不同进程之间进行通信的能力。它的设计旨在提供一种简单、高效、安全的通信方式,使得增加新的软件组件变得更加容易,并且能够轻松地维护现有的组件。DBus通信机制被广泛应用于Linux操作系统和桌面环境中,如GNOME、KDE等桌面环境。DBus还提供了一些重要的通信功能,这些功能在一些Linux发行版、应用程序等中非常常见,例如,开机提示、系统监控、命名服务等。
DBus(Desktop Bus)是一个在Linux和其他类Unix操作系统中使用的系统总线,用于进程间通信和设备插入/拔出通知。
DBus最早是由Red Hat公司的开发人员在2002年-2003年之间创建的,最初是为了解决在GNOME桌面环境中横跨多个进程和应用程序实现通信和设备管理的问题。
2003年,DBus被引入D-BUS 0.23版本中,并成为Freedesktop.org项目的一部分。2006年,DBus 1.0版发布,这是一个重要的版本,它引入了一些新特性和API,并增加了平台支持的广泛性。此后,DBus的更新一直继续,新版本不断增加新功能,解决Bug和安全问题,并提高性能。
今天,DBus已被广泛采用,并成为Linux及其他类Unix操作系统中的标准通信机制,受到许多桌面环境、应用程序和设备管理器的使用。同时,DBus的专业性质使得该技术被云计算、大数据、物联网等领域越来越广泛地运用。
DBus(Desktop Bus)是一个在Linux和其他类Unix操作系统中使用的系统总线,用于进程间通信和设备插入/拔出通知。DBus的重要性在以下几个方面:
提供了进程间通信的标准机制:DBus提供了一种标准的、可靠的机制来进行进程间通信,使得不同应用程序可以相互通信和协作,从而使得整个系统更加智能化和高效化。
跨平台支持:DBus支持多种类Unix操作系统,包括Linux,FreeBSD,Solaris等,使得DBus可以作为跨平台的进程间通信机制来使用。
设备管理:DBus可以用于设备管理,当用户插入或拔出设备时,DBus会自动检测并发送通知给相关应用程序,从而使得应用程序可以根据设备的状态来正确地响应用户的操作。
代码重用:DBus提供了多种程序语言的绑定,包括C++,Python等,使得DBus可以快速地集成到现有系统中,并且减少开发时间和成本。
总之,DBus的重要性不仅在于提供了进程间通信的标准机制,还在于多方面的适应性和可靠性,使得DBus成为Linux及其他类Unix操作系统中的标准通信机制,并且被广泛采用于各种应用程序和设备管理器中。
操作系统: DBus可以在操作系统内部实现不同进程间的消息传递和数据交换。例如,Linux中的systemd就使用DBus来管理各个系统服务之间的通讯和信息交互。
消息总线: 在DBus消息总线中,各个组件可以以客户端-服务端的方式一起工作。DBus服务可以在总线上注册自己提供的服务,客户端则可以使用DBus总线查询和调用这些服务。DBus采用基于总线广播的方式,将服务和请求发送到相应的组件,这样就可以实现组件之间的通信。
框架和应用程序之间的通信:DBus可以作为框架和应用程序之间通信的抽象层,提供了统一的接口和协议,使得应用程序能够使用DBus实现与框架之间的通信。例如,Gnome桌面环境中,DBus被广泛应用,用于各个应用程序的交互,例如通知、系统状态、文件管理等。
远程通信:通过DBus的远程通信,可以允许客户端程序通过DBus连接到远程服务器上的DBus,并向服务器发送请求以获取所需的服务。DBus消息传递机制可用于传递标准和自定义消息,从而实现不同的通信需求。
消息总线(Message Bus):DBus通过在消息总线上发布和订阅消息的方式实现组件之间的通信。总线是一个中央的消息处理器,组件可以将消息发送到总线上,总线根据消息内容将其路由到订阅了该消息的组件中。DBus采用基于广播的方式,支持点到点和广播通信。
发送接收(Send-Reveice):DBus还支持一对一的点对点通信模式,即发送接收模式。在这种模式下,组件可以直接向其他组件发送消息或接收其他组件发送的消息,而不必使用DBus总线。
远程调用(Remote Procedure Calls,RPC):DBus还支持远程调用,即可以在不同的计算机或者进程之间进行远程过程调用。DBus使用的RPC机制类似于本地的函数调用,使得开发者可以像本地函数调用那样进行远程函数调用,从而在分布式系统中实现服务调用。
总之,DBus通过支持消息总线、点对点通信和远程调用来实现组件间的通信。消息总线是DBus最常用的通信模式,采用基于总线广播的方式,将消息从发送者路由到接收者。DBus发送接收模式则针对一对一的点对点通信而设计,而DBus的RPC机制则是用于在分布式系统中进行远程函数调用。
DBus API是DBus提供给应用程序和组件使用的一系列API,它们使得DBus消息总线可以方便地被集成到应用程序或组件中,以实现高效的通信。DBus API通常包括C和Python两种编程语言接口。
DBus C API是DBus的C语言编程接口,DBus C API支持通信(实现客户端和服务器的DBus连接)、处理错误和注册/注销服务等功能。DBus C API提供以下常用的函数:
DBus Python API是DBus的Python语言编程接口,DBus Python API提供Python接口来支持DBus通信。DBus Python API包括dbus、dbus.service、dbus.mainloop和dbus.types等模块,DBus Python API提供以下常用的类和方法:
使用DBus API进行DBus通信的过程通常包括以下步骤:
总之,DBus API能够提供简单易用的接口,使得DBus在应用程序和组件中的集成变得简单和快速。使用DBus API可以实现高效的DBus通信,从而提高了应用程序和组件的通信效率和质量。可运行代码
DBusConnection *dbus_bus_get (DBusBusType type, DBusError *error); /* 建立和总线的连接 */
int dbus_bus_request_name (DBusConnection *connection,
const char *name,
unsigned int flags,
DBusError *error); /* 注册连接名称 */
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_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); /* 发送返回消息 */
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); /* 获得返回消息 */
一个信号监听的示例
监听信号:
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
static gboolean send_ping (DBusConnection *bus);
int main (int argc, char **argv)
{
GMainLoop *loop;
DBusConnection *bus;
DBusError error;
/* Create a new event loop to run in */
loop = g_main_loop_new (NULL, FALSE);
/* Get a connection to the session bus */
dbus_error_init (&error);
bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
if (!bus) {
g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
dbus_error_free (&error);
return 1;
}
/* Set up this connection to work in a GLib event loop */
dbus_connection_setup_with_g_main (bus, NULL);
/* Every second call send_ping() with the bus as an argument*/
g_timeout_add (1000, (GSourceFunc)send_ping, bus);
/* Start the event loop */
g_main_loop_run (loop);
return 0;
}
static gboolean
send_ping (DBusConnection *bus)
{
DBusMessage *message;
/* Create a new signal "Ping" on the "com.burtonini.dbus.Signal" interface,
* from the object "/com/burtonini/dbus/ping". */
message = dbus_message_new_signal ("/com/burtonini/dbus/ping",
"com.burtonini.dbus.Signal", "Ping");
/* Append the string "Ping!" to the signal */
const char *ping = "Ping!";
dbus_message_append_args (message,
DBUS_TYPE_STRING, &ping,
DBUS_TYPE_INVALID);
/* Send the signal */
dbus_connection_send (bus, message, NULL);
/* Free the signal now we have finished with it */
dbus_message_unref (message);
/* Tell the user we send a signal */
g_print("Ping!\n");
/* Return TRUE to tell the event loop we want to be called again */
return TRUE;
}
发送信号
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
static gboolean send_ping (DBusConnection *bus);
int
main (int argc, char **argv)
{
GMainLoop *loop;
DBusConnection *bus;
DBusError error;
/* Create a new event loop to run in */
loop = g_main_loop_new (NULL, FALSE);
/* Get a connection to the session bus */
dbus_error_init (&error);
bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
if (!bus) {
g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
dbus_error_free (&error);
return 1;
}
/* Set up this connection to work in a GLib event loop */
dbus_connection_setup_with_g_main (bus, NULL);
/* Every second call send_ping() with the bus as an argument*/
g_timeout_add (1000, (GSourceFunc)send_ping, bus);
/* Start the event loop */
g_main_loop_run (loop);
return 0;
}
static gboolean
send_ping (DBusConnection *bus)
{
DBusMessage *message;
/* Create a new signal "Ping" on the "com.burtonini.dbus.Signal" interface,
* from the object "/com/burtonini/dbus/ping". */
message = dbus_message_new_signal ("/com/burtonini/dbus/ping",
"com.burtonini.dbus.Signal", "Ping");
/* Append the string "Ping!" to the signal */
const char *ping = "Ping!";
dbus_message_append_args (message,
DBUS_TYPE_STRING, &ping,
DBUS_TYPE_INVALID);
/* Send the signal */
dbus_connection_send (bus, message, NULL);
/* Free the signal now we have finished with it */
dbus_message_unref (message);
/* Tell the user we send a signal */
g_print("Ping!\n");
/* Return TRUE to tell the event loop we want to be called again */
return TRUE;
}
有关于信号和方法调用的
服务端:
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h> /* for glib main loop */
const char *version = "0.1";
GMainLoop *mainloop;
/*
* This is the XML string describing the interfaces, methods and
* signals implemented by our 'Server' object. It's used by the
* 'Introspect' method of 'org.freedesktop.DBus.Introspectable'
* interface.
*
* Currently our tiny server implements only 3 interfaces:
*
* - org.freedesktop.DBus.Introspectable
* - org.freedesktop.DBus.Properties
* - org.example.TestInterface
*
* 'org.example.TestInterface' offers 3 methods:
*
* - Ping(): makes the server answering the string 'Pong'.
* It takes no arguments.
*
* - Echo(): replies the passed string argument.
*
* - EmitSignal(): send a signal 'OnEmitSignal'
*
* - Quit(): makes the server exit. It takes no arguments.
*/
const char *server_introspection_xml =
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
"<node>\n"
" <interface name='org.freedesktop.DBus.Introspectable'>\n"
" <method name='Introspect'>\n"
" <arg name='data' type='s' direction='out' />\n"
" </method>\n"
" </interface>\n"
" <interface name='org.freedesktop.DBus.Properties'>\n"
" <method name='Get'>\n"
" <arg name='interface' type='s' direction='in' />\n"
" <arg name='property' type='s' direction='in' />\n"
" <arg name='value' type='s' direction='out' />\n"
" </method>\n"
" <method name='GetAll'>\n"
" <arg name='interface' type='s' direction='in'/>\n"
" <arg name='properties' type='a{sv}' direction='out'/>\n"
" </method>\n"
" </interface>\n"
" <interface name='org.example.TestInterface'>\n"
" <property name='Version' type='s' access='read' />\n"
" <method name='Ping' >\n"
" <arg type='s' direction='out' />\n"
" </method>\n"
" <method name='Echo'>\n"
" <arg name='string' direction='in' type='s'/>\n"
" <arg type='s' direction='out' />\n"
" </method>\n"
" <method name='EmitSignal'>\n"
" </method>\n"
" <method name='Quit'>\n"
" </method>\n"
" <signal name='OnEmitSignal'>\n"
" </signal>"
" </interface>\n"
"</node>\n";
/*
* This implements 'Get' method of DBUS_INTERFACE_PROPERTIES so a
* client can inspect the properties/attributes of 'TestInterface'.
*/
DBusHandlerResult server_get_properties_handler(const char *property, DBusConnection *conn, DBusMessage *reply)
{
if (!strcmp(property, "Version"))
{
dbus_message_append_args(reply,
DBUS_TYPE_STRING, &version,
DBUS_TYPE_INVALID);
}
else
/* Unknown property */
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
if (!dbus_connection_send(conn, reply, NULL))
return DBUS_HANDLER_RESULT_NEED_MEMORY;
return DBUS_HANDLER_RESULT_HANDLED;
}
/*
* This implements 'GetAll' method of DBUS_INTERFACE_PROPERTIES. This
* one seems required by g_dbus_proxy_get_cached_property().
*/
DBusHandlerResult server_get_all_properties_handler(DBusConnection *conn, DBusMessage *reply)
{
DBusHandlerResult result;
DBusMessageIter array, dict, iter, variant;
const char *property = "Version";
/*
* All dbus functions used below might fail due to out of
* memory error. If one of them fails, we assume that all
* following functions will fail too, including
* dbus_connection_send().
*/
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
dbus_message_iter_init_append(reply, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
/* Append all properties name/value pairs */
property = "Version";
dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &property);
dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, "s", &variant);
dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &version);
dbus_message_iter_close_container(&dict, &variant);
dbus_message_iter_close_container(&array, &dict);
dbus_message_iter_close_container(&iter, &array);
if (dbus_connection_send(conn, reply, NULL))
result = DBUS_HANDLER_RESULT_HANDLED;
return result;
}
/*
* This function implements the 'TestInterface' interface for the
* 'Server' DBus object.
*
* It also implements 'Introspect' method of
* 'org.freedesktop.DBus.Introspectable' interface which returns the
* XML string describing the interfaces, methods, and signals
* implemented by 'Server' object. This also can be used by tools such
* as d-feet(1) and can be queried by:
*
* $ gdbus introspect --session --dest org.example.TestServer --object-path /org/example/TestObject
*/
DBusHandlerResult server_message_handler(DBusConnection *conn, DBusMessage *message, void *data)
{
DBusHandlerResult result;
DBusMessage *reply = NULL;
DBusError err;
bool quit = false;
fprintf(stderr, "Got D-Bus request: %s.%s on %s\n",
dbus_message_get_interface(message),
dbus_message_get_member(message),
dbus_message_get_path(message));
/*
* Does not allocate any memory; the error only needs to be
* freed if it is set at some point.
*/
dbus_error_init(&err);
if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
{
if (!(reply = dbus_message_new_method_return(message)))
goto fail;
dbus_message_append_args(reply,
DBUS_TYPE_STRING, &server_introspection_xml,
DBUS_TYPE_INVALID);
}
else if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "Get"))
{
const char *interface, *property;
if (!dbus_message_get_args(message, &err,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID))
goto fail;
if (!(reply = dbus_message_new_method_return(message)))
goto fail;
result = server_get_properties_handler(property, conn, reply);
dbus_message_unref(reply);
return result;
}
else if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "GetAll"))
{
if (!(reply = dbus_message_new_method_return(message)))
goto fail;
result = server_get_all_properties_handler(conn, reply);
dbus_message_unref(reply);
return result;
}
else if (dbus_message_is_method_call(message, "org.example.TestInterface", "Ping"))
{
const char *pong = "Pong";
if (!(reply = dbus_message_new_method_return(message)))
goto fail;
dbus_message_append_args(reply,
DBUS_TYPE_STRING, &pong,
DBUS_TYPE_INVALID);
}
else if (dbus_message_is_method_call(message, "org.example.TestInterface", "Echo"))
{
const char *msg;
if (!dbus_message_get_args(message, &err,
DBUS_TYPE_STRING, &msg,
DBUS_TYPE_INVALID))
goto fail;
if (!(reply = dbus_message_new_method_return(message)))
goto fail;
dbus_message_append_args(reply,
DBUS_TYPE_STRING, &msg,
DBUS_TYPE_INVALID);
}
else if (dbus_message_is_method_call(message, "org.example.TestInterface", "EmitSignal"))
{
if (!(reply = dbus_message_new_signal("/org/example/TestObject",
"org.example.TestInterface",
"OnEmitSignal")))
goto fail;
if (!dbus_connection_send(conn, reply, NULL))
return DBUS_HANDLER_RESULT_NEED_MEMORY;
/* Send a METHOD_RETURN reply. */
reply = dbus_message_new_method_return(message);
}
else if (dbus_message_is_method_call(message, "org.example.TestInterface", "Quit"))
{
/*
* Quit() has no return values but a METHOD_RETURN
* reply is required, so the caller will know the
* method was successfully processed.
*/
reply = dbus_message_new_method_return(message);
quit = true;
}
else
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
fail:
if (dbus_error_is_set(&err))
{
if (reply)
dbus_message_unref(reply);
reply = dbus_message_new_error(message, err.name, err.message);
dbus_error_free(&err);
}
/*
* In any cases we should have allocated a reply otherwise it
* means that we failed to allocate one.
*/
if (!reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
/* Send the reply which might be an error one too. */
result = DBUS_HANDLER_RESULT_HANDLED;
if (!dbus_connection_send(conn, reply, NULL))
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
dbus_message_unref(reply);
if (quit)
{
fprintf(stderr, "Server exiting...\n");
g_main_loop_quit(mainloop);
}
return result;
}
const DBusObjectPathVTable server_vtable = {
.message_function = server_message_handler};
int main(void)
{
DBusConnection *conn;
DBusError err;
int rv;
dbus_error_init(&err);
/* connect to the daemon bus */
conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (!conn)
{
fprintf(stderr, "Failed to get a session DBus connection: %s\n", err.message);
goto fail;
}
rv = dbus_bus_request_name(conn, "org.example.TestServer", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if (rv != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
{
fprintf(stderr, "Failed to request name on bus: %s\n", err.message);
goto fail;
}
if (!dbus_connection_register_object_path(conn, "/org/example/TestObject", &server_vtable, NULL))
{
fprintf(stderr, "Failed to register a object path for 'TestObject'\n");
goto fail;
}
/*
* For the sake of simplicity we're using glib event loop to
* handle DBus messages. This is the only place where glib is
* used.
*/
printf("Starting dbus tiny server v%s\n", version);
mainloop = g_main_loop_new(NULL, false);
/* Set up the DBus connection to work in a GLib event loop */
dbus_connection_setup_with_g_main(conn, NULL);
/* Start the glib event loop */
g_main_loop_run(mainloop);
return EXIT_SUCCESS;
fail:
dbus_error_free(&err);
return EXIT_FAILURE;
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
#include <unistd.h>
// 建立与session D-Bus daemo的连接,并设定连接的名字,相关的代码已经多次使用过了
DBusConnection *connect_dbus()
{
DBusError err;
DBusConnection *connection;
int ret;
// Step 1: connecting session bus
/* initialise the erroes */
dbus_error_init(&err);
/* Connect to Bus*/
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Connection Err : %s/n", err.message);
dbus_error_free(&err);
}
if (connection == NULL)
return NULL;
// step 2: 设置BUS name,也即连接的名字。
ret = dbus_bus_request_name(connection, "test.wei.source", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Name Err : %s/n", err.message);
dbus_error_free(&err);
}
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return NULL;
return connection;
}
void send_a_method_call(DBusConnection *connection, char *param)
{
DBusError err;
DBusMessage *msg;
DBusMessageIter arg;
DBusPendingCall *pending;
dbus_bool_t *stat;
dbus_uint32_t *level;
dbus_error_init(&err);
// 针对目的地地址,请参考图,创建一个method call消息。 Constructs a new message to invoke a method on a remote object.
msg = dbus_message_new_method_call("org.example.TestServer", "/org/example/TestObject", "org.example.TestInterface", "Echo");
if (msg == NULL)
{
g_printerr("Message NULL");
return;
}
// 为消息添加参数。Append arguments
dbus_message_iter_init_append(msg, &arg);
if (!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, ¶m))
{
g_printerr("Out of Memory!");
exit(1);
}
// 发送消息并获得reply的handle 。Queues a message to send, as with dbus_connection_send() , but also returns a DBusPendingCall used to receive a reply to the message.
if (!dbus_connection_send_with_reply(connection, msg, &pending, -1))
{
g_printerr("Out of Memory!");
exit(1);
}
if (pending == NULL)
{
g_printerr("Pending Call NULL: connection is disconnected ");
dbus_message_unref(msg);
return;
}
dbus_connection_flush(connection);
dbus_message_unref(msg);
// waiting a reply,在发送的时候,已经获取了method reply的handle,类型为DBusPendingCall。
// block until we recieve a reply, Block until the pending call is completed.
dbus_pending_call_block(pending);
// get the reply message,Gets the reply, or returns NULL if none has been received yet.
msg = dbus_pending_call_steal_reply(pending);
if (msg == NULL)
{
fprintf(stderr, "Reply Null/n");
exit(1);
}
// free the pending message handle
dbus_pending_call_unref(pending);
// read the parameters
if (!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "Message has no arguments!/n");
// else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_BOOLEAN)
// fprintf(stderr, "Argument is not boolean!/n");
// else
// dbus_message_iter_get_basic(&arg, &stat);
///
if (dbus_message_iter_get_arg_type(&arg) == DBUS_TYPE_STRING)
{
const char *value;
dbus_message_iter_get_basic(&arg, &value);
printf("Method call response returned string \"%s\".\n", value);
}
else
{
// 返回类型不正确
g_error("Error: unexpected return type from method call.");
}
///
// if (!dbus_message_iter_next(&arg))
// fprintf(stderr, "Message has too few arguments!/n");
// else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_UINT32)
// fprintf(stderr, "Argument is not int!/n");
// else
// dbus_message_iter_get_basic(&arg, &level);
// printf("Got Reply: %d, %d/n", stat, level);
dbus_message_unref(msg);
}
int main(int argc, char **argv)
{
DBusConnection *connection;
connection = connect_dbus();
if (connection == NULL)
return -1;
send_a_method_call(connection, "Hello, D-Bus");
return 0;
}
dbus-daemon --config-file=/overlay/debug-allow-all.conf --fork --print-address
配置内容如:
<!-- Bus that listens on a debug pipe and doesn't create any restrictions -->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<type>session</type>
<listen>unix:tmpdir=/tmp</listen>
<standard_session_servicedirs />
<policy context="default">
<!-- Allow everything to be sent -->
<allow send_destination="*" eavesdrop="true"/>
<!-- Allow everything to be received -->
<allow eavesdrop="true"/>
<!-- Allow anyone to own anything -->
<allow own="*"/>
<allow user="*"/>
</policy>
</busconfig>
export DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-W1ALCK2LKH,guid=c3b18510d26f9a9231d849800000411f
dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames
dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.Introspectable.Introspect
发送信号
如果你要通过 dbus-send 命令发送字符串类型的信号,需要使用 –dest 参数指定目标程序和对象。下面是一个发送字符串类型信号的例子:
dbus-send --session --type=signal --dest=com.example.SomeService /com/example/SomeObject com.example.SomeInterface.SomeSignal string:"hello world"
这个命令的具体解释如下:
如果信号的参数是其他数据类型,可以使用不同的参数类型指定参数的类型。例如,如果要发送一个整数类型的参数,可以使用下面的命令:
dbus-send --session --type=signal --dest=com.example.SomeService /com/example/SomeObject com.example.SomeInterface.SomeSignal int32:123
这个命令的意思是向目标程序 com.example.SomeService 的对象路径 /com/example/SomeObject 发送名为 com.example.SomeInterface.SomeSignal 的信号,该信号包含一个 32 位的整数参数,值为 123。
dbus-send --session --type=method_call --print-reply --dest=org.example.TestServer /org/example/TestObject org.example.TestInterface.Ping
---
dbus-send --session --type=method_call --print-reply --dest=org.example.TestServer /org/example/TestObject org.example.TestInterface.Echo string:"Ping"