D-Bus的用例
16.2.2 D-Bus的用例
http://book.51cto.com 2009-12-15 09:40 徐诚/高莹婷 清华大学出版社 我要评论(0)
- 摘要:《Linux环境C程序设计》第16章进程间通信,本章讲解进程间通信的机制和以管道方式进行进程间通信的相关系统调用函数,同时也介绍基于D-Bus消息总线系统实现更为简单方便的进程间通信方式。本节为大家介绍D-Bus的用例。
- 标签:Linux C程序设计
Oracle帮您准确洞察各个物流环节
16.2.2 D-Bus的用例
在使用GNOME桌面环境的Linux系统中,通常用GLib库提供的函数来管理总线。在测试下列用例前,首先需要安装GTK+开发包(见22.3节)并配置编译环境。该用例一共包含两个程序文件,每个程序文件需单独编译成为可执行文件。
1.消息发送程序
"dbus-ding-send.c"程序每秒通过会话总线发送一个参数为字符串Ding!的信号。该程序的源代码如下:
- #include <glib.h> // 包含glib库
- #include <dbus/dbus-glib.h> // 包含
glib库中D-Bus管理库 - #include <stdio.h>
- static gboolean send_ding(DBusConnection *bus);// 定义
发送消息函数的原型 - int main ()
- {
- GMainLoop *loop; // 定义
一个事件循环对象的指针 - DBusConnection *bus; // 定义
总线连接对象的指针 - DBusError error; // 定义
D-Bus错误消息对象 - loop = g_main_loop_new(NULL, FALSE); // 创建新事件循环对象
- dbus_error_init (&error); // 将错误消
息对象连接到D-Bus - // 错误消息对象
- bus = dbus_bus_get(DBUS_BUS_SESSION, &error);// 连接到总线
- if (!bus) { // 判断是否连接错误
- g_warning("连接到D-Bus失败: %s", error.message);
- // 使用GLib输出错误警告信息
- dbus_error_free(&error); // 清除错误消息
- return 1;
- }
- dbus_connection_setup_with_g_main(bus, NULL);
- // 将总线设为
接收GLib事件循环 - g_timeout_add(1000, (GSourceFunc)send_ding, bus);
- // 每隔1000ms调用一次
send_ding()函数 - // 将总线指针作为参数
- g_main_loop_run(loop); // 启动事件循环
- return 0;
- }
- static gboolean send_ding(DBusConnection *bus) // 定义发
送消息函数的细节 - {
- DBusMessage *message; // 创建消息对象指针
- message = dbus_message_new_signal("/com/burtonini/dbus/ding",
- "com.burtonini.dbus.Signal",
- "ding"); //
创建消息对象并标识路径 - dbus_message_append_args(message,
- DBUS_TYPE_STRING, "ding!",
- DBUS_TYPE_INVALID); //
将字符串Ding!定义为消息 - dbus_connection_send(bus, message, NULL); // 发送该消息
- dbus_message_unref(message); // 释放消息对象
- g_print("ding!\n"); // 该函数
等同与标准输入输出
// 库的printf() - return TRUE;
- }
main()函数创建一个GLib事件循环,获得会话总线的一个连接,并将D-Bus事件处理集成到GLib事件循环之中。然后它创建了一个名为send_ding()函数作为间隔为一秒的计时器,并启动事件循环。send_ding()函数构造一个来自于对象路径"/com/burtonini/dbus/ding"和接口"com.burtonini.dbus.Signal"的新的Ding 信号。然后,字符串Ding!作为参数添加到信号中并通过总线发送。在标准输出中会打印一条消息以让用户知道发送了一个信号。
2.消息接收程序
dbus-ding-listen.c程序通过会话总线接收dbus-ding-send.c程序发送到消息。该程序的源代码如下:
- #include <glib.h> // 包含glib库
- #include <dbus/dbus-glib.h> // 包含glib库中D-Bus管理库
- static DBusHandlerResult signal_filter // 定义接收消息函数的原型
- (DBusConnection *connection, DBusMessage *message, void *user_data);
- int main()
- {
- GMainLoop *loop; // 定义
一个事件循环对象的指针 - DBusConnection *bus; // 定义
- 总线连接对象的指针
- DBusError error; // 定义
D-Bus错误消息对象 - loop = g_main_loop_new(NULL, FALSE); // 创建新
事件循环对象 - dbus_error_init(&error); // 将错误消
息对象连接到D-Bus - // 错误消息对象
- bus = dbus_bus_get(DBUS_BUS_SESSION, &error); // 连接到总线
- if (!bus) { // 判断是否连接错误
- g_warning("连接到D-Bus失败: %s", error.message);
- // 使用GLib输出错误警告信息
- dbus_error_free(&error); // 清除错误消息
- return 1;
- }
- dbus_connection_setup_with_g_main(bus, NULL);
- // 将总线设
为接收GLib事件循环 - dbus_bus_add_match(bus, "type='signal',interface
='com.burtonini.dbus.Signal'"); // 定义匹配器 - dbus_connection_add_filter(bus, signal_filter, loop, NULL);
- // 调用函数接收消息
- g_main_loop_run(loop); // 启动事件循环
- return 0;
- }
- static DBusHandlerResult // 定义接收消息函数的细节
- signal_filter (DBusConnection *connection,
DBusMessage *message, void *user_data) - {
- GMainLoop *loop = user_data; // 定义事件
循环对象的指针,并与主函
// 数中的同步 - if (dbus_message_is_signal // 接收连接
成功消息,判断是否连接 - // 失败
- (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
"Disconnected")) { - g_main_loop_quit (loop); // 退出主循环
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- if (dbus_message_is_signal(message, "com.burtonini.dbus.Signal",
- "Ping")) {
- // 指定
消息对象路径,判断是否成功 - DBusError error; // 定义错误对象
- char *s;
- dbus_error_init(&error); // 将错误消息对
象连接到D-Bus错误 - // 消息对象
- if (dbus_message_get_args // 接
收消息,并判断是否有错误 - (message, &error, DBUS_TYPE_STRING, &s,
DBUS_TYPE_INVALID)) { - g_print("接收到的消息是: %s\n", s); // 输出接收到的消息
- dbus_free (s); // 清除该消息
- }
- else { // 有
错误时执行下列语句 - g_print("消息已收到,但有错误提示: %s\n", error.message);
- dbus_error_free (&error);
- }
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
该程序侦听dbus-ping-send.c程序正在发出的信号。main()函数和前面一样启动,创建一个到总线的连接。然后它声明愿意在使用 com.burtonini.dbus.Signal接口的信号被发送时得到通知,将signal_filter()函数设置为通知函数,然后进入事件循环。当满足匹配的消息被发送时,signal_func()函数会被调用。
如果需要确定在接收消息时如何处理,可通过检测消息头实现。若收到的消息为总线断开信号,则主事件循环将被终止,因为监听的总线已经不存在了。若收到其他的消息,首先将收到的消息与期待的消息进行比较,两者相同则输出其中参数,并退出程序。两者不相同则告知总线并没有处理该消息,这样消息会继续保留在总线中供别的程序处理。

浙公网安备 33010602011771号