https://blog.csdn.net/weixin_45566765/article/details/125028296
一、D-Bus简介
1. D-Bus是什么
D-Bus最主要的用途是在 Linux 桌面环境为进程提供通信,同时能将 Linux 桌面环境和 Linux 内核事件作为消息传递到进程。D-Bus(其中D原先是代表桌面“Desktop” 的意思),即:用于桌面操作系统的通信总线。
D-Bus的主要概念为总线,注册后的进程可通过总线接收或传递消息,进程也可注册后等待内核事件响应,例如等待网络状态的转变或者计算机发出关机指令。
D-Bus是为Linux系统开发的进程间通信(IPC)和远程过程调用(RPC)机制,使用统一的通信协议来代替现有的各种IPC解决方案。D-Bus允许系统级进程(如:打印机和硬件驱动服务)和普通用户进程进行通信。
2. D-Bus特性
D-Bus使用一个快速的二进制消息传递协议,D-Bus协议的低延迟和低消耗特点适用于同一台机器的通信。D-Bus的规范目前由freedesktop.org项目定义,可供所有团体使用。
D-Bus不和低层的IPC直接竞争,比如sockets,shared memory或message queues。低层IPC有自己的特点,和D-Bus并不冲突。
与其他重量级的进程间通信技术不同,D-Bus是非事务的。D-Bus使用了状态以及连接的概念,比UDP等底层消息传输协议更“聪明”。但另一方面,D-Bus传送的是离散消息,与TCP协议将数据看做“流”有所不同。D-Bus支持点对点的消息传递以及广播/订阅式的通信。
总结如下:
1、D-BUS的协议是低延迟而且低开销的,设计小巧且高效,以便最小化传送时间。从设计上避免往返交互并允许异步操作。 2、协议是二进制的,而不是文本,排除序列化过程。 3、考虑了字节序问题。 4、易用性:按照消息而不是字节流来工作,并且自动地处理了许多困难的IPC问题,并且D-Bus库以可以封装的方式来设计,开发者可以使用框架里存在的对象/类型系统,而不用学习一种新的专用于IPC的对象/类型系统。 5、请求时启动服务以及安全策略。 6、支持多语言(C/C++/Java/C#/Python/Ruby),多平台(Linux/windows/maemo)。 7、采用C语言,而不是C++。 H、由于基本上不用于internet上的IPC,因此对本地IPC进行了特别优化。 8、提供服务注册,理论上可以进行无限扩展。 9、支持广播类型的通信。 10、带有异常处理的通用远程调用接口;
二、D-Bus架构
1. 结构层次
D-Bus进程间通信主要有三层架构: 1.底层接口层:主要是通过libdbus这个函数库,给予系统使用DBus的能力。
2.总线层:主 要Message bus daemon这个总线守护进程提供的,在Linux系统启动时运行,负责进程间的消息路由和传递,其中包括Linux内核和Linux桌面环境的消息传递。总线守护进程可同时与多个应用程序相连,并能把来自一个应用程序的消息路由到0或者多个其他程序。
3.应用封装层:通过一系列基于特定应用程序框架将DBus的底层接口封装成友好的Wrapper库,供不同开发人员使用。比如libdbus-glib, libdbus-python.
2.系统总线和会话总线
在一台机器上总线守护有多个实例(instance)。这些总线之间都是相互独立的。
一个持久的系统总线(system bus)
它在引导时就会启动。这个总线由操作系统和后台进程使用 ,安全性非常好,以使得任意的应用程序不能欺骗系统事件。 它是桌面会话和操作系统的通信,这里操作系统一般而言包括内核和系统守护进程。 这种通道的最常用的方面就是发送系统消息,比如:插入一个新的存储设备;有新的网络连接;等等。
还将有很多会话总线(session buses)‘ 普通进程创建,可同时存在多条。会话总线属于某个进程私有,它用于进程间传递消息。
三、D-Bus编程基础知识
1.address地址
使用d-bus的应用程序既可以是server也可以是client,server监听到来的连接,client连接到 server,一旦连接建立,消息就可以流转。点对点通信时就是一个 server 和 一个 client;如果使用dbus daemon,所有的应用程序都是client,bus daemon 是server,daemon监听所有的连接,应用程序初始化连接到daemon 。
dbus地址指明server将要监听的地方,client将要连接的地方,例如,地址:unix:path=/tmp/abcdef表明 server将在/tmp/abcdef路径下监听unix域的socket,client也将连接到这个socket。一个地址也可以指明是 TCP/IP的socket,或者是其他的。
当使用bus daemon时,libdbus会从环境变量中(DBUS_SESSION_BUS_ADDRESS)自动认识“会话daemon”的地址。如果是系统 daemon,它会检查指定的socket路径获得地址,也可以使用环境变量(DBUS_SESSION_BUS_ADDRESS)进行设定。
2. bus name 总线名字
当一个应用连接到 bus daemon,daemon 立即会分配一个名字给这个连接,称为 Unique Connection Name, 这个唯一标识的名字以冒号 “:” 开头,例如 :1.2,这个名字在 daemon 的整个生命周期是唯一的。
但是这种名字总是临时分配,无法确定的,也难以记忆,因此应用可以要求有另外一个公共名 well-known name 来对应这个唯一标识 ,就像我们使用域名来映射 IP地址一样 。例如可以使用 org.fmddlmyy.Test 来映射 :1.2。这样我们就可以使用公共名 连接到 DBus 服务。
3. 原生对象和对象路径
d-bus 的底层接口是没有这些对象的概念的,它提供的是一种叫对象路径(object path),用于让高层接口绑定到各个对象中去,允许远端应用程序指向它们。object path就像是一个文件路径,可以叫做 /org/kde/kspread/sheets/3/cells/4/5 等。
4. 接口 Interface
接口是一组方法和信号,每一个对象支持一个或者多个接口,接口定义一个对象实体的类型。 D-Bus使用简单的命名空间字符串来表示接口,例如 org.freedesktop.Introspectable。
5. Methods 和 Signals
每一个对象有两类成员:方法和信号:
方法就是一个函数,具有有输入和输出; 信号会被广播,感兴趣的对象可以处理这个 信号,同时信号中也可以带有相关的数据。
在 D-BUS 中有四种类型的消息:
1、方法调用(method call) # 在对象上执行一个方法 2、方法返回(method return) # 返回方法执行的结果 3、信号(signal) # 调用方法产生的异常 4、错误(error)# 通知指定的信号发生了,可以想象成“事件”。
要执行D-BUS对象的方法,您需要向对象发送一个方法调用消息 。 它将完成一些处理(就是执行了对象中的Method,Method是可以带有输入参数的)并返回,返回消息或者错误消息。 信号的不同之处在于它们不返回任何内容 :既没有“信号返回”消息,也没有任何类型的错误消息。
6. 总结:方法所需要的参数
要在指定的对象中调用指定的方法,需要知道的参数如下: Address -> [Bus Name] -> Path -> Interface -> Method
bus name是可选的,除非是希望把消息送到特定的应用中才需要。interface也是可选的,有一些历史原因,DCOP不需要指定接口,因为DCOP在同一个对象中禁止同名的方法。
四、D-Bus运行环境
1. 运行环境安装
sudo apt-get install dbus
sudo apt-get install libgtk2.0-dev
sudo apt-get install libdbus-glib-1-dev
sudo apt-get install d-feet
同时下载一个简单的 DBus 程序:链接,运行方法:
tar -zxvf hello-dbus3-0.1.tar.gz
# 编译 cd hello-dbus3-0.1/ ./autogen.sh ./configure make
# 运行 cd src ./example-service
运行 d-feet,打开 Session bus,找到 “org.fmddlmyy.Test” 连接名,这个链接就是我们刚刚运行的一个D-Bus程序:
在右侧展开栏我们会发现 org.fmddlmyy.Test.Basic 下有一个 Add 方法,我们点击它,输入 1,2,点击执行,可以看到给我们返回了结果:
通过上面的操作我们通过 d-feet 发起了一次 d-bus 请求。
2. dbus-send以及dbus-monitor
dbus提供了两个小工具:dbus-send和dbus-monitor。我们可以用dbus-send发送消息。用dbus-monitor监视总线上流动的消息。 让我们通过dbus-send发送消息来调用前面的Add方法,这时dbus-send充当了应用程序B。用dbus-monitor观察调用过程中的消息
保持上面的example-server运行,新建两个窗口一个运行dubs-monitor一个运行如下命令
dbus-send --session --type = method_call --print-reply --dest = org.fmddlmyy.Test /TestObj org.fmddlmyy.Test.Basic.Add int32:100 int32:999
dbus-send的详细用法可以参阅手册。调用远程方法的一般形式是
$ dbus-send [ --system | --session] --type = method_call --print-reply --dest = 连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值
dbus-send支持的参数类型包括:string, int32, uint32, double, byte, boolea
dubs-monitor窗口返回的消息如下:
method call time = 1653831830.713656 sender = :1.97 -> destination = org.freedesktop.DBus serial = 1 path = /org/freedesktop/DBus; interface = org.freedesktop.DBus; member = Hello
method return time = 1653831830.713685 sender = org.freedesktop.DBus -> destination = :1.97 serial = 1 reply_serial = 1
string ":1.97"
signal time = 1653831830.713696 sender = org.freedesktop.DBus -> destination = ( null destination) serial = 10 path = /org/freedesktop/DBus; interface = org.freedesktop.DBus; member = NameOwnerChanged
string ":1.97"
string ""
string ":1.97"
signal time = 1653831830.713712 sender = org.freedesktop.DBus -> destination = :1.97 serial = 2 path = /org/freedesktop/DBus; interface = org.freedesktop.DBus; member = NameAcquired
string ":1.97"
method call time = 1653831830.714160 sender = :1.97 -> destination = org.fmddlmyy.Test serial = 2 path = /TestObj; interface = org.fmddlmyy.Test.Basic; member = Add
int32 123
int32 456
method return time = 1653831830.714310 sender = :1.95 -> destination = :1.97 serial = 7 reply_serial = 2
int32 579
signal time = 1653831830.715690 sender = org.freedesktop.DBus -> destination = :1.97 serial = 6 path = /org/freedesktop/DBus; interface = org.freedesktop.DBus; member = NameLost
string ":1.97"
signal time = 1653831830.715717 sender = org.freedesktop.DBus -> destination = ( null destination) serial = 11 path = /org/freedesktop/DBus; interface = org.freedesktop.DBus; member = NameOwnerChanged
string ":1.97"
string ":1.97"
string ""
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
上述一次完整的 d-bus 通信的流程
3.Dbus通信流程总结
(1) 方法调用的一般流程:
1.使用不同语言绑定的dbus高层接口,都提供了一些代理对象,调用其他进程里面的远端对象就像是在本地进程中的调用一样。应用调用代理上的方法,代理将构造一个方法调用消息给远端的进程。 2.在DBUS的底层接口中,应用需要自己构造方法调用消息(method call message),而不能使用代理。 3.方法调用消息里面的内容有:目的进程的bus name,方法的名字,方法的参数,目的进程的对象路径,以及可选的接口名称。 4.方法调用消息是发送到bus daemon中的。 5.bus daemon查找目标的bus name,如果找到,就把这个方法发送到该进程中,否则,daemon会产生错误消息,作为应答消息给发送进程。 6. 目标进程解开消息,在dbus底层接口中,会立即调用方法,然后发送方法的应答消息给daemon。在dbus高层接口中,会先检测对象路径,接口, 方法名称,然后把它转换成对应的对象(如GObject,QT中的QObject等)的方法,然后再将应答结果转换成应答消息发给daemon。 7.bus daemon接受到应答消息,将把应答消息直接发给发出调用消息的进程。 8.应答消息中可以包容很多返回值,也可以标识一个错误发生,当使用绑定时,应答消息将转换为代理对象的返回值,或者进入异常
(2) 信号的一般流程:
1.当使用dbus底层接口时,信号需要应用自己创建和发送到daemon,使用dbus高层接口时,可以使用相关对象进行发送,如Glib里面提供的信号触发机制。 2.信号包含的内容有:信号的接口名称,信号名称,发送进程的bus name,以及其他参数。 3.任何进程都可以依据”match rules”注册相关的信号,daemon有一张注册的列表。 4.daemon检测信号,决定哪些进程对这个信号感兴趣,然后把信号发送给这些进程。 5.每个进程收到信号后,如果是使用了dbus高层接口,可以选择触发代理对象上的信号。如果是dbus底层接口,需要检查发送者名称和信号名称,然后决定怎么做。
五、DBUS编程
1. 通用代码介绍
(1)连接代码
首先,客户端必须要连接上 Dbus,一般来说,系统中会有一个 System Bus 和一个 Session Bus。其次,你需要在 Dbus 中注册一个名字,用于标识自己。为了简单起见,这里先不考虑重名的情况:
DBusError err;
DBusConnection* conn;
int ret;
dbus_error_init ( & err) ;
// connect to the bus conn = dbus_bus_get ( DBUS_BUS_SESSION, & err) ; if ( dbus_error_is_set ( & err) ) {
fprintf ( stderr , “Connection Error (%s)\n” , err. message) ; dbus_error_free ( & err) ; } if ( NULL == conn) {
exit ( 1 ) ; } // request a name on the bus ret = dbus_bus_request_name ( conn, “test.method.server” , DBUS_NAME_FLAG_REPLACE_EXISTING , & err) ; if ( dbus_error_is_set ( & err) ) {
fprintf ( stderr , “Name Error (%s)\n” , err. message) ; dbus_error_free ( & err) ; } if ( DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
exit ( 1 ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
一般来说,连接上 Dbus 和注册一个名称,应该是在程序最开始运行的时候就会进行的操作。
当然,在程序结束的时候,需要关闭掉与 Dbus 的连接。使用下面的函数:
dbus_connection_close ( conn) ;
(2) 发送信号(Sending Signal)
信号是一种广播的消息,你可以简单的发出一个信号,这样,所有连接在 DBus 总线上并注册了接受对应信号的进程,都会收到这个信号。
为了发出一个信号,需要的只是创建一个 DBusMessage 对象来代表信号 ,然后追加上一些需要发出的参数 ,就可以发向总线了。
发完之后还需要释放掉 Message。如果内存不足的话,这下面不少函数都会返回 false,所以一般情况下你都需要处理这些情况的返回值。
dbus_uint32_t serial = 0 ;
DBusMessage* msg;
DBusMessageIter args;
// create a signal and check for errors msg = dbus_message_new_signal ( “/test/signal/Object” , // object name of the signal “test.signal.Type” , // interface name of the signal “Test” ) ; // name of the signal if ( NULL == msg) {
fprintf ( stderr , “Message Null\n” ) ; exit ( 1 ) ; }
// append arguments onto signal dbus_message_iter_init_append ( msg, & args) ; if ( ! dbus_message_iter_append_basic ( & args, DBUS_TYPE_STRING, & sigvalue) ) {
fprintf ( stderr , “Out Of Memory!\n” ) ; exit ( 1 ) ; }
// send the message and flush the connection if ( ! dbus_connection_send ( conn, msg, & serial) ) {
fprintf ( stderr , “Out Of Memory!\n” ) ; exit ( 1 ) ; } dbus_connection_flush ( conn) ;
// free the message dbus_message_unref ( msg) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
(3) 调用方法(Call a Methond)
调用一个远程方法(remote method)与发送一个信号(sending a signal)是很类似的。需要创建一个 DBusMessage,然后通过注册在 DBus 上的名称指定发送的对象,追加相应的参数,但调用方法分为两种,一种是阻塞式的,另一种则可以异步调用 。异步调用的时候会得到一个 DBusMessage* 的返回,从这个 DBusMessage 中可以获取一些返回的参数。
调用方法1
DBusMessage* msg;
DBusMessageIter args;
DBusPendingCall* pending;
msg = dbus_message_new_method_call ( “test.method.server” , // target for the method call “/test/method/Object” , // object to call on “test.method.Type” , // interface to call on “Method” ) ; // method name if ( NULL == msg) {
fprintf ( stderr , “Message Null\n” ) ; exit ( 1 ) ; }
// append arguments dbus_message_iter_init_append ( msg, & args) ; if ( ! dbus_message_iter_append_basic ( & args, DBUS_TYPE_STRING, & param) ) {
fprintf ( stderr , “Out Of Memory!\n” ) ; exit ( 1 ) ; }
// send message and get a handle for a reply if ( ! dbus_connection_send_with_reply ( conn, msg, & pending, - 1 ) ) {
// -1 is default timeout fprintf ( stderr , “Out Of Memory!\n” ) ; exit ( 1 ) ; } if ( NULL == pending) {
fprintf ( stderr , “Pending Call Null\n” ) ; exit ( 1 ) ; } dbus_connection_flush ( conn) ;
// free message dbus_message_unref ( msg) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
调用方法2
bool stat;
dbus_uint32_t level;
// block until we receive a reply dbus_pending_call_block ( pending) ;
// get the reply message msg = dbus_pending_call_steal_reply ( pending) ; if ( NULL == msg) {
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, & args) ) fprintf ( stderr , “Message has no arguments!\n” ) ; else if ( DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type ( & args) ) fprintf ( stderr , “Argument is not boolean!\n” ) ; else dbus_message_iter_get_basic ( & args, & stat) ;
if ( ! dbus_message_iter_next ( & args) ) fprintf ( stderr , “Message has too few arguments!\n” ) ; else if ( DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type ( & args) ) fprintf ( stderr , “Argument is not int!\n” ) ; else dbus_message_iter_get_basic ( & args, & level) ;
printf ( “Got Reply: %d, %d\n” , stat, level) ;
// free reply and close connection dbus_message_unref ( msg) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
(4) 接收消息(Receiving a Signal)
接下来的两种操作是从总线读取消息并处理这些消息。
要接收一个消息,你首先需要告诉 DBus 你对什么样的消息感兴趣 :
dbus_bus_add_match ( conn,
"type='signal',interface='test.signal.Type'" ,
& err) ;
dbus_connection_flush ( conn) ;
if ( dbus_error_is_set ( & err) ) {
fprintf ( stderr , "Match Error (%s)\n" , err. message) ;
exit ( 1 ) ;
}
然后,进程就可以在一个循环中等待这类消息的发生了 :
/ loop listening for signals being emmitted
while ( true) {
<span class="token comment">// non blocking read of the next available message</span>
<span class="token function">dbus_connection_read_write</span><span class="token punctuation">(</span>conn<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
msg <span class="token operator">=</span> <span class="token function">dbus_connection_pop_message</span><span class="token punctuation">(</span>conn<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// loop again if we haven't read a message</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">NULL</span> <span class="token operator">==</span> msg<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">continue</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// check if the message is a signal from the correct interface and with the correct name</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">dbus_message_is_signal</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token string">"test.signal.Type"</span><span class="token punctuation">,</span> <span class="token string">"Test"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token comment">// read the parameters</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_init</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token operator">&</span>args<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token function">fprintf</span><span class="token punctuation">(</span><span class="token constant">stderr</span><span class="token punctuation">,</span> <span class="token string">"Message has no arguments!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>DBUS_TYPE_STRING <span class="token operator">!=</span> <span class="token function">dbus_message_iter_get_arg_type</span><span class="token punctuation">(</span><span class="token operator">&</span>args<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token function">fprintf</span><span class="token punctuation">(</span><span class="token constant">stderr</span><span class="token punctuation">,</span> <span class="token string">"Argument is not string!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">dbus_message_iter_get_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>args<span class="token punctuation">,</span> <span class="token operator">&</span>sigvalue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"Got Signal with value %s\n"</span><span class="token punctuation">,</span> sigvalue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// free the message</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
(5) 提供被远程调用的方法(Exposing a Method to be called)
在(3) 调用方法(Call a Methond)中,我们看到了调用一个远程方法,这节就是告诉我们怎么样提供一个方法让别的应用程序调用。用下面的程序,就可以把方法关联在那些提供给外部的方法上,并解析出相应的参数,最后构建一个消息返回给调用方法的应用程序。
远程调用的方法1
while ( true) {
dbus_connection_read_write ( conn, 0 ) ;
msg = dbus_connection_pop_message ( conn) ;
<span class="token comment">// loop again if we haven't got a message</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">NULL</span> <span class="token operator">==</span> msg<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">continue</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// check this is a method call for the right interface and method</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">dbus_message_is_method_call</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token string">"test.method.Type"</span><span class="token punctuation">,</span> <span class="token string">"Method"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token function">reply_to_method_call</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> conn<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// free the message</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
远程调用方法2:
void reply_to_method_call ( DBusMessage* msg, DBusConnection* conn)
{
DBusMessage* reply;
DBusMessageIter args;
DBusConnection* conn;
bool stat = true;
dbus_uint32_t level = 21614 ;
dbus_uint32_t serial = 0 ;
char * param = "" ;
<span class="token comment">// read the arguments</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_init</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token operator">&</span>args<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token function">fprintf</span><span class="token punctuation">(</span><span class="token constant">stderr</span><span class="token punctuation">,</span> <span class="token string">"Message has no arguments!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>DBUS_TYPE_STRING <span class="token operator">!=</span> <span class="token function">dbus_message_iter_get_arg_type</span><span class="token punctuation">(</span><span class="token operator">&</span>args<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token function">fprintf</span><span class="token punctuation">(</span><span class="token constant">stderr</span><span class="token punctuation">,</span> <span class="token string">"Argument is not string!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">else</span>
<span class="token function">dbus_message_iter_get_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>args<span class="token punctuation">,</span> <span class="token operator">&</span>param<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"Method called with %s\n"</span><span class="token punctuation">,</span> param<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// create a reply from the message</span>
reply <span class="token operator">=</span> <span class="token function">dbus_message_new_method_return</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// add the arguments to the reply</span>
<span class="token function">dbus_message_iter_init_append</span><span class="token punctuation">(</span>reply<span class="token punctuation">,</span> <span class="token operator">&</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_append_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>args<span class="token punctuation">,</span> DBUS_TYPE_BOOLEAN<span class="token punctuation">,</span> <span class="token operator">&</span>stat<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">fprintf</span><span class="token punctuation">(</span><span class="token constant">stderr</span><span class="token punctuation">,</span> <span class="token string">"Out Of Memory!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">exit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_append_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>args<span class="token punctuation">,</span> DBUS_TYPE_UINT32<span class="token punctuation">,</span> <span class="token operator">&</span>level<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">fprintf</span><span class="token punctuation">(</span><span class="token constant">stderr</span><span class="token punctuation">,</span> <span class="token string">"Out Of Memory!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">exit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// send the reply && flush the connection</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_connection_send</span><span class="token punctuation">(</span>conn<span class="token punctuation">,</span> reply<span class="token punctuation">,</span> <span class="token operator">&</span>serial<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">fprintf</span><span class="token punctuation">(</span><span class="token constant">stderr</span><span class="token punctuation">,</span> <span class="token string">"Out Of Memory!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">exit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">dbus_connection_flush</span><span class="token punctuation">(</span>conn<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// free the reply</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>reply<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
2. 实例代码
(1) 客户端代码
client.c
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <dbus/dbus.h>
DBusConnection init_bus ( ) {
DBusConnection connection; DBusError err; int ret;
<span class="token function">dbus_error_init</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//连接到dbus,建立一个连接,称为对象</span>
connection <span class="token operator">=</span> <span class="token function">dbus_bus_get</span><span class="token punctuation">(</span>DBUS_BUS_SESSION<span class="token punctuation">,</span> <span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_error_is_set</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"connection error: :%s -- %s\n"</span><span class="token punctuation">,</span> err<span class="token punctuation">.</span>name<span class="token punctuation">,</span> err<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_error_free</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//为这个对象分配一个名字</span>
ret <span class="token operator">=</span> <span class="token function">dbus_bus_request_name</span><span class="token punctuation">(</span>connection<span class="token punctuation">,</span> <span class="token string">"hello.world.client"</span><span class="token punctuation">,</span> DBUS_NAME_FLAG_REPLACE_EXISTING<span class="token punctuation">,</span> <span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_error_is_set</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"Name error: %s -- %s\n"</span><span class="token punctuation">,</span> err<span class="token punctuation">.</span>name<span class="token punctuation">,</span> err<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_error_free</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>ret <span class="token operator">!=</span> DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER<span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> connection<span class="token punctuation">;</span>
}
void send_signal ( DBusConnection connection) {
DBusMessage msg; DBusMessageIter arg; char * str = “hello world!” ;
<span class="token comment">//创建一个signal对象</span>
<span class="token comment">//param1: path (这个逻辑来说,可以是任何字符串,只要符合规则即可)</span>
<span class="token comment">//param2: interface (一样)</span>
<span class="token comment">//param3: 信号方法名(必须与服务端名匹配)</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>msg <span class="token operator">=</span> <span class="token function">dbus_message_new_signal</span><span class="token punctuation">(</span><span class="token string">"/hello"</span><span class="token punctuation">,</span> <span class="token string">"aa.bb.cc"</span><span class="token punctuation">,</span> <span class="token string">"alarm_test"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"message is NULL\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
# if 0 //这个看需求添加,一般来说,信号是一种单向广播,加上这一句变单向单播 //param2: bus_name if ( ! dbus_message_set_destination ( msg, “hello.world.service” ) ) {
printf ( “memory error\n” ) ; } # endif
<span class="token comment">//添加参数的一些接口</span>
<span class="token function">dbus_message_iter_init_append</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token operator">&</span>arg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_message_iter_append_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">,</span> DBUS_TYPE_STRING<span class="token punctuation">,</span> <span class="token operator">&</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//入队</span>
<span class="token function">dbus_connection_send</span><span class="token punctuation">(</span>connection<span class="token punctuation">,</span> msg<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//发送</span>
<span class="token function">dbus_connection_flush</span><span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//释放内存</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
}
void send_method_call ( DBusConnection connection) {
DBusMessage msg; DBusMessageIter arg; DBusPendingCall * pending; int a = 100 ; int b = 99 ; int sum;
msg <span class="token operator">=</span> <span class="token function">dbus_message_new_method_call</span><span class="token punctuation">(</span><span class="token string">"hello.world.service"</span><span class="token punctuation">,</span> <span class="token string">"/hello/world"</span><span class="token punctuation">,</span><span class="token string">"hello.world"</span><span class="token punctuation">,</span> <span class="token string">"add"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>msg <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"no memory\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">dbus_message_iter_init_append</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token operator">&</span>arg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_append_basic</span> <span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">,</span> DBUS_TYPE_INT32<span class="token punctuation">,</span><span class="token operator">&</span>a<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"no memory!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_append_basic</span> <span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">,</span> DBUS_TYPE_INT32<span class="token punctuation">,</span><span class="token operator">&</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"no memory!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//入队message,等待回复</span>
<span class="token comment">//param1: 连接描述符</span>
<span class="token comment">//param2: message</span>
<span class="token comment">//param3: 相当于一个回调的一个描述符,为了获了返回的消息</span>
<span class="token comment">//param4: 超时间. -1代表无限</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_connection_send_with_reply</span> <span class="token punctuation">(</span>connection<span class="token punctuation">,</span> msg<span class="token punctuation">,</span> <span class="token operator">&</span>pending<span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"no memeory!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>pending <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"Pending is NULL, may be disconnect...\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//send</span>
<span class="token function">dbus_connection_flush</span><span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//阻塞,直到接收到一个响应.</span>
<span class="token function">dbus_pending_call_block</span> <span class="token punctuation">(</span>pending<span class="token punctuation">)</span><span class="token punctuation">;</span>
msg <span class="token operator">=</span> <span class="token function">dbus_pending_call_steal_reply</span> <span class="token punctuation">(</span>pending<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>msg <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"reply is null. error\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//释放pending内存 </span>
<span class="token function">dbus_pending_call_unref</span><span class="token punctuation">(</span>pending<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//解析参数</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_init</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token operator">&</span>arg<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"no argument, error\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_message_iter_get_arg_type</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">)</span> <span class="token operator">!=</span> DBUS_TYPE_INT32<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"paramter type error\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">dbus_message_iter_get_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">,</span> <span class="token operator">&</span>sum<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">" a(%d) + b(%d) = %d\n"</span><span class="token punctuation">,</span>a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> sum<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
}
int main ( int argc, char argv) {
DBusConnection * connection;
connection <span class="token operator">=</span> <span class="token function">init_bus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>connection <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"connect to bus failed...\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//发送一个信号及一个方法调用</span>
<span class="token function">send_signal</span><span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">send_method_call</span><span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
(2) 服务端代码
service.c
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <dbus/dbus.h>
# include <unistd.h>
DBusConnection init_bus ( ) {
DBusConnection connection; DBusError err; int ret = 0 ;
<span class="token function">dbus_error_init</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//与session dbus 建立连接</span>
<span class="token comment">//param1:bus type = {DBUS_BUS_SESSION, DBUS_BUS_SYSTEM} 一个系统dbus, 一个普通用户dbus</span>
<span class="token comment">//param2:错误信息,包括错误名与错误信息.</span>
connection <span class="token operator">=</span> <span class="token function">dbus_bus_get</span><span class="token punctuation">(</span>DBUS_BUS_SESSION<span class="token punctuation">,</span> <span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_error_is_set</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"Connection Error: %s--%s\n"</span><span class="token punctuation">,</span> err<span class="token punctuation">.</span>name<span class="token punctuation">,</span> err<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_error_free</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//为连接设置一个bus name: bus_name;</span>
<span class="token comment">//param 1: 连接描述符</span>
<span class="token comment">//param 2: 请求bus要分配的bus name(逻辑上讲,bus name可以是任何字符串,只要符合命名规则)</span>
<span class="token comment">//param 3: flags ={DBUS_NAME_FLAG_REPLACE_EXISTING, </span>
<span class="token comment">// DBUS_NAME_FLAG_ALLOW_REPLACEMENT,</span>
<span class="token comment">// DBUS_NAME_FLAG_DO_NOT_QUEUE</span>
<span class="token comment">// }</span>
<span class="token comment">//param 4: err info</span>
ret <span class="token operator">=</span> <span class="token function">dbus_bus_request_name</span><span class="token punctuation">(</span>connection<span class="token punctuation">,</span> <span class="token string">"hello.world.service"</span><span class="token punctuation">,</span> DBUS_NAME_FLAG_REPLACE_EXISTING<span class="token punctuation">,</span> <span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_error_is_set</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span> <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"Name Error: %s--%s\n"</span><span class="token punctuation">,</span> err<span class="token punctuation">.</span>name<span class="token punctuation">,</span> err<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_error_free</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>ret <span class="token operator">!=</span> DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER<span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token comment">//注册感兴趣的signal: 来自接口dbus.test.signal.sender</span>
<span class="token comment">//param1: 连接描述符</span>
<span class="token comment">//param2: match rule (常用的类型: sender=</span>
<span class="token comment">// interface=</span>
<span class="token comment">// type=</span>
<span class="token comment">// member= )</span>
<span class="token comment">//param3: err info</span>
<span class="token comment">//只设置一个type = signal,表示所有信号都接受.也可以加上接口,发送者bus_name</span>
<span class="token function">dbus_bus_add_match</span><span class="token punctuation">(</span>connection<span class="token punctuation">,</span> <span class="token string">"type='signal'"</span><span class="token punctuation">,</span> <span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//阻塞,直到消息发送成功.</span>
<span class="token function">dbus_connection_flush</span><span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_error_is_set</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"add Match Error %s--%s\n"</span><span class="token punctuation">,</span> err<span class="token punctuation">.</span>name<span class="token punctuation">,</span> err<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_error_free</span><span class="token punctuation">(</span><span class="token operator">&</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> connection<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> connection<span class="token punctuation">;</span>
}
void handle_message ( DBusConnection connection) {
DBusMessage msg; DBusMessageIter arg; char * str;
<span class="token keyword">while</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token comment">//param1: 连接描述符</span>
<span class="token comment">//param2: 超时时间, -1无限超时时间</span>
<span class="token function">dbus_connection_read_write</span><span class="token punctuation">(</span>connection<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//从队列中取出一条消息</span>
msg <span class="token operator">=</span> <span class="token function">dbus_connection_pop_message</span><span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>msg <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">continue</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//这里应该过滤path,暂且不做</span>
<span class="token comment">//打印出消息对象路径</span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"path: %s\n"</span><span class="token punctuation">,</span> <span class="token function">dbus_message_get_path</span> <span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//param1: message</span>
<span class="token comment">//param2: interface 这个名字必须与发送那个接口一样.才能处理</span>
<span class="token comment">//param3: singal name 方法名也必须一样.</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_message_is_signal</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token string">"aa.bb.cc"</span><span class="token punctuation">,</span> <span class="token string">"alarm_test"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token comment">//解析message 参数,0为无参数.</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_init</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token operator">&</span>arg<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"no argument\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//获取第一个参数类型</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_message_iter_get_arg_type</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">)</span> <span class="token operator">!=</span> DBUS_TYPE_INVALID<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token comment">//获取参数的值</span>
<span class="token function">dbus_message_iter_get_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">,</span><span class="token operator">&</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"recv param --: %s\n"</span><span class="token punctuation">,</span> str<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_message_is_method_call</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token string">"hello.world"</span><span class="token punctuation">,</span> <span class="token string">"add"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span><span class="token comment">//处理 add 远程调用.</span>
DBusMessage <span class="token operator">*</span>rp<span class="token punctuation">;</span>
DBusMessageIter r_arg<span class="token punctuation">;</span>
<span class="token keyword">int</span> a <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> b <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> sum <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"service: add function\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_init</span><span class="token punctuation">(</span>msg<span class="token punctuation">,</span> <span class="token operator">&</span>arg<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"no argument!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">goto</span> out<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">dbus_message_iter_get_arg_type</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">)</span> <span class="token operator">!=</span> DBUS_TYPE_INT32<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"argument error\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">goto</span> out<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">dbus_message_iter_get_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">,</span> <span class="token operator">&</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_message_iter_next</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"too few argument!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">goto</span> out<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//check argument type....</span>
<span class="token function">dbus_message_iter_get_basic</span><span class="token punctuation">(</span><span class="token operator">&</span>arg<span class="token punctuation">,</span> <span class="token operator">&</span>b<span class="token punctuation">)</span><span class="token punctuation">;</span>
sum <span class="token operator">=</span> a <span class="token operator">+</span> b<span class="token punctuation">;</span>
out: //new 一个回应对象 rp = dbus_message_new_method_return ( msg) ; dbus_message_iter_init_append ( rp, & r_arg) ; if ( ! dbus_message_iter_append_basic ( & r_arg, DBUS_TYPE_INT32, & sum) ) {
printf ( “no memory!!\n” ) ; return ; }
<span class="token comment">//param3: 这个跟消息序列有关</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">dbus_connection_send</span><span class="token punctuation">(</span>connection<span class="token punctuation">,</span> rp<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"no memory!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">dbus_connection_flush</span><span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>rp<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//释放空间</span>
<span class="token function">dbus_message_unref</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//dbus_bus_remove_match();</span>
}
int main ( int argc, char argv) {
int ret = 0 ; DBusConnection * connection;
connection <span class="token operator">=</span> <span class="token function">init_bus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>connection <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"connect the dbus failed...\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">handle_message</span><span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
(3)执行结果
客户端
服务端
参考博客: D-Bus 学习 DBUS基础知识(非常全面) DBus 入门与应用 -- DBus 的 C 编程接口 dbus 简单编程(二)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)