博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dbus的hello world
阅读量:4055 次
发布时间:2019-05-25

本文共 10936 字,大约阅读时间需要 36 分钟。

来自: 

dbus的是一个低延迟,低开销,高可用性的IPC机制。通过dbus的daemon,可以实现进程间通信和函数调用。Windows下,dbus的开发库可以去这里()下载,在VS设置头文件和lib库的路径即可。若是要编写其Hello World,自然包含客户端和服务端两部分。下面的Hello World代码包含了发送消息和函数调用两部分,分别描述之。

      1) 信号

假设客户端发送消息,服务端接收。客户端发送消息的流程如下: 

1.创建于dbus daemon的会话连接。 
2.创建消息,若有消息参数,附加之(这个一般都有) 
3.通过连接发送消息。

1: int main (int argc, char *argv[])
2: {
3:     DBusError dberr;
4:     DBusConnection *dbconn;
5:     DBusMessage *dbmsg;
6:     char *text;
7: 
8:     // 初始话错误信息的结构体
9:     dbus_error_init (&dberr);
10:
11:     // 创建会话连接
12:     dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr);
13:     if (dbus_error_is_set (&dberr)) {
14:         fprintf (stderr, "getting session bus failed: %s/n", dberr.message);
15:         dbus_error_free (&dberr);
16:         return EXIT_FAILURE;
17:     }
18: 
19:     // 创建消息
20:     dbmsg = dbus_message_new_signal ("/com/wiley/test",
21:                                      "com.wiley.test",
22:                                      "TestSignal");
23:     if (!dbmsg) {
24:         fprintf (stderr, "Could not create a new signal/n");
25:         return EXIT_FAILURE;
26:     }
27: 
28:     // 消息中,附加文本
29:     text = "Hello World";
30:     if (!dbus_message_append_args (
31:         dbmsg, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID)) {
32:         fprintf(stderr, "Out Of Memory!/n");
33:         return EXIT_FAILURE;
34:     }
35: 
36:     // 发送消息
37:     if (!dbus_connection_send (dbconn, dbmsg, NULL)) {
38:         fprintf(stderr, "Out Of Memory!/n");
39:         return EXIT_FAILURE;
40:     }
41:     dbus_connection_flush(dbconn);
42: 
43:     printf ("Sending signal to D-Bus/n");
44: 
45:     // 释放消息
46:     dbus_message_unref (dbmsg);
47: 
48:     // 释放会话连接
49:     dbus_connection_unref (dbconn);
50: 
51:     return EXIT_SUCCESS;
52: }

服务端接收消息的流程如下: 

1.创建于dbus daemon的会话连接。 
2.为本次连接设置名称,客户端可以通过此名称进行通信 
3.设置消息对应的回调函数 
4.添加消息匹配规则 
5.进入处理消息的循环

1: static DBusHandlerResult
2: filter_func (DBusConnection *connection,
3:              DBusMessage *message,
4:              void *user_data)
5: {
6:     dbus_bool_t handled = FALSE;
7:     char *signal_text = NULL;
8: 
9:     // 若为指定信号
10:     if (dbus_message_is_signal (message, "com.wiley.test", "TestSignal")) {
11:         DBusError dberr;
12:         // 初始化错误结构体
13:         dbus_error_init (&dberr);
14:         // 获取消息的参数
15:         dbus_message_get_args (message, &dberr, DBUS_TYPE_STRING, &signal_text, DBUS_TYPE_INVALID);
16:         if (dbus_error_is_set (&dberr)) {
17:             fprintf (stderr, "Error getting message args: %s", dberr.message);
18:             dbus_error_free (&dberr);
19:         } else {
20:             printf ("Received TestSignal with value of: '%s'/n", signal_text);
21:             // 标识本消息已处理
22:             handled = TRUE;
23:         }
24:     }
25:     // 返回值决定该消息是否处理
26:     return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
27: }
28: 
29: 
30: int main (int argc, char *argv[])
31: {
32:     DBusError dberr;
33:     DBusConnection *dbconn;
34: 
35:     // 初始话错误信息的结构体
36:     dbus_error_init (&dberr);
37:
38:     // 创建会话
39:     dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr);
40:     if (dbus_error_is_set (&dberr)) {
41:         fprintf (stderr, "getting session bus failed: %s/n", dberr.message);
42:         dbus_error_free (&dberr);
43:         return EXIT_FAILURE;
44:     }
45: 
46:     // 向daemon追加了一条路由到该应用程序入口
47:     dbus_bus_request_name (dbconn, "com.wiley.test",
48:                            DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);
49:     if (dbus_error_is_set (&dberr)) {
50:         fprintf (stderr, "requesting name failed: %s/n", dberr.message);
51:         dbus_error_free (&dberr);
52:         return EXIT_FAILURE;
53:     }
54: 
55:     // 设置处理消息的函数
56:     if (!dbus_connection_add_filter (dbconn, filter_func, NULL, NULL)) {
57:         return EXIT_FAILURE;
58:     }
59: 
60:     // 添加消息匹配规则
61:     dbus_bus_add_match (dbconn,
62:                         "type='signal',interface='com.wiley.test'",
63:                         &dberr);
64:     if (dbus_error_is_set (&dberr)) {
65:         fprintf (stderr, "Could not match: %s", dberr.message);
66:         dbus_error_free (&dberr);
67:         return EXIT_FAILURE;
68:     }
69: 
70:     // 分派消息的Loop
71:     while (dbus_connection_read_write_dispatch (dbconn, -1))
72:         ; /* empty loop body */
73: 
74:     return EXIT_SUCCESS;
75: }

      2) 跨进程调用 

跨进程调用中,客户端和服务端的流程差不多,假设客户端跨进程调用服务端函数。 

客户端

1: int main (int argc, char *argv[])
2: {
3:     DBusMessage* msg;
4:     DBusMessageIter args;
5:     DBusConnection* conn;
6:     DBusError err;
7:     DBusPendingCall* pending;
8:     char* param = "no param";
9:     int ret;
10:     dbus_bool_t stat = FALSE;
11:     dbus_uint32_t level = 0;
12: 
13:     printf("Calling remote method with %s/n", param);
14: 
15:     // 初始化错误
16:     dbus_error_init(&err);
17: 
18:     // 获取会话连接
19:     conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
20:     if (dbus_error_is_set(&err)) {
21:         fprintf(stderr, "Connection Error (%s)/n", err.message);
22:         dbus_error_free(&err);
23:     }
24:     if (NULL == conn) {
25:         exit(1);
26:     }
27: 
28:     // 设置连接名称,若存在则替换
29:     ret = dbus_bus_request_name(conn, "test.method.caller", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
30:     if (dbus_error_is_set(&err)) {
31:         fprintf(stderr, "Name Error (%s)/n", err.message);
32:         dbus_error_free(&err);
33:     }
34:     if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
35:         exit(1);
36:     }
37: 
38:     // 创建方法调用的消息
39:     msg = dbus_message_new_method_call("com.test.dbus.server",    // target for the method call
40:                                        "/test/method/Object",    // object to call on
41:                                        "test.method.Interface", // interface to call on
42:                                        "Method");                // method name
43:     if (NULL == msg) {
44:         fprintf(stderr, "Message Null/n");
45:         exit(1);
46:     }
47: 
48:     // 附加参数
49:     dbus_message_iter_init_append(msg, &args);
50:     if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &param)) {
51:         fprintf(stderr, "Out Of Memory!/n");
52:         exit(1);
53:     }
54: 
55:     // 发送消息(-1表示使用默认超时)
56:     if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) {
57:         fprintf(stderr, "Out Of Memory!/n");
58:         exit(1);
59:     }
60:     if (NULL == pending) {
61:         fprintf(stderr, "Pending Call Null/n");
62:         exit(1);
63:     }
64: 
65:     // 阻塞直到发送的消息队列为空
66:     dbus_connection_flush(conn);
67: 
68:     printf("Request Sent/n");
69: 
70:     // 释放消息
71:     dbus_message_unref(msg);
72: 
73:     // 阻塞至消息返回
74:     dbus_pending_call_block(pending);
75: 
76:     // 获取返回消息
77:     msg = dbus_pending_call_steal_reply(pending);
78:     if (NULL == msg) {
79:         fprintf(stderr, "Reply Null/n");
80:         exit(1);
81:     }
82:
83:     // 释放pending
84:     dbus_pending_call_unref(pending);
85: 
86:     // 读取参数
87:     if (!dbus_message_iter_init(msg, &args))
88:         fprintf(stderr, "Message has no arguments!/n");
89:     else if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&args))
90:         fprintf(stderr, "Argument is not boolean!/n");
91:     else
92:         dbus_message_iter_get_basic(&args, &stat);
93: 
94:     if (!dbus_message_iter_next(&args))
95:         fprintf(stderr, "Message has too few arguments!/n");
96:     else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
97:         fprintf(stderr, "Argument is not int!/n");
98:     else
99:         dbus_message_iter_get_basic(&args, &level);
100: 
101:     printf("Got Reply: %d, %d/n", stat, level);
102: 
103:     // 释放方法返回的消息
104:     dbus_message_unref(msg);
105: 
106:     return EXIT_SUCCESS;
107: }

服务端

1: static
2: void reply_to_method_call(DBusMessage* msg, DBusConnection* conn)
3: {
4:     DBusMessage* reply;
5:     DBusMessageIter args;
6:     dbus_bool_t stat = TRUE;
7:     dbus_uint32_t level = 21614;
8:     dbus_uint32_t serial = 0;
9:     char* param = "";
10: 
11:     // 读取参数
12:     if (!dbus_message_iter_init(msg, &args)) // 获取参数
13:         fprintf(stderr, "Message has no arguments!/n");
14:     else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) // 参数类型不为字符串
15:         fprintf(stderr, "Argument is not string!/n");
16:     else { // 参数为字符串
17:         dbus_message_iter_get_basic(&args, &param);
18:     }
19: 
20:     printf("Method called with %s/n", param);
21: 
22:     // 创建返回类型的消息,对应于调用的消息
23:     reply = dbus_message_new_method_return(msg);
24: 
25:     // 初始化返回的参数
26:     dbus_message_iter_init_append(reply, &args);
27:     if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &stat)) { // 附加基本类型的值到消息中
28:         fprintf(stderr, "Out Of Memory!/n");
29:         exit(1);
30:     }
31:     if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &level)) { // 附加基本类型的值到消息中
32:         fprintf(stderr, "Out Of Memory!/n");
33:         exit(1);
34:     }
35: 
36:     // 发送返回消息
37:     if (!dbus_connection_send(conn, reply, &serial)) {
38:         fprintf(stderr, "Out Of Memory!/n");
39:         exit(1);
40:     }
41:     dbus_connection_flush(conn);
42: 
43:     // 释放方法返回的消息
44:     dbus_message_unref(reply);
45: }
46: 
47: int main (int argc, char *argv[])
48: {
49:     DBusError dberr;
50:     DBusConnection * dbconn;
51:     DBusMessage * msg;
52:     int ret;
53: 
54:     // 初始话错误信息的结构体
55:     dbus_error_init (&dberr);
56:     // 创建会话
57:     dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr);
58:     if (dbus_error_is_set (&dberr)) {
59:         fprintf (stderr, "getting session bus failed: %s/n", dberr.message);
60:         dbus_error_free (&dberr);
61:         return EXIT_FAILURE;
62:     }
63: 
64:     // 为本次连接设置名称,客户端可以通过此名称进行通信
65:     ret = dbus_bus_request_name (dbconn, "com.test.dbus.server",
66:                            DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);
67:     if (dbus_error_is_set (&dberr)) {
68:         fprintf (stderr, "requesting name failed: %s/n", dberr.message);
69:         dbus_error_free (&dberr);
70:         return EXIT_FAILURE;
71:     }
72:     if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
73:         fprintf(stderr, "Not Primary Owner (%d)/n", ret);
74:         exit(1);
75:     }
76: 
77:     // 循环等待消息
78:     while (true) {
79:         // 非阻塞的获取下一个消息
80:         // TODO: 如何阻塞?
81:         dbus_connection_read_write(dbconn, 0);
82: 
83:         // 获取消息
84:         msg = dbus_connection_pop_message(dbconn);
85:         if (NULL == msg) {
86:             // sleep(1);
87:             continue;
88:         }
89: 
90:         // 相应消息调用
91:         if (dbus_message_is_method_call(msg, "test.method.Interface", "Method"))
92:             reply_to_method_call(msg, dbconn);
93: 
94:         // 释放引用
95:         dbus_message_unref(msg);
96:     }
97: 
98:     return EXIT_SUCCESS;
99: }

转载地址:http://jpoci.baihongyu.com/

你可能感兴趣的文章
Linux 粘滞位 suid sgid
查看>>
C#控件集DotNetBar安装及破解
查看>>
Winform皮肤控件IrisSkin4.dll使用
查看>>
Winform多线程
查看>>
C# 托管与非托管
查看>>
Node.js中的事件驱动编程详解
查看>>
mongodb 命令
查看>>
MongoDB基本使用
查看>>
mongodb管理与安全认证
查看>>
nodejs内存控制
查看>>
nodejs Stream使用中的陷阱
查看>>
MongoDB 数据文件备份与恢复
查看>>
数据库索引介绍及使用
查看>>
MongoDB数据库插入、更新和删除操作详解
查看>>
MongoDB文档(Document)全局唯一ID的设计思路
查看>>
mongoDB简介
查看>>
Redis持久化存储(AOF与RDB两种模式)
查看>>
memcached工作原理与优化建议
查看>>
Redis与Memcached的区别
查看>>
redis sharding方案
查看>>