D-Bus
简介
待补充。。。
标准接口
org.freedesktop.DBus.Peer
org.freedesktop.DBus.Peer.Ping() //方法
org.freedesktop.DBus.Peer.GetMachineId(out STRING machine_uuid) //方法
org.freedesktop.DBus.Introspectable
org.freedesktop.DBus.Introspectable.Introspect(输出 STRING xml_data)//方法
org.freedesktop.DBus.Properties
org.freedesktop.DBus.Properties.Get(
in STRING interface_name,
in STRING property_name,
out VARIANT value
); //方法
org.freedesktop.DBus.Properties.Set(
in STRING interface_name,
in STRING property_name,
in VARIANT value
); //方法
org.freedesktop.DBus.Properties.GetAll(
in STRING interface_name,
out ARRAY of DICT_ENTRY<STRING,VARIANT> props); //方法
org.freedesktop.DBus.ObjectManager
org.freedesktop.DBus.ObjectManager.GetManagedObjects(
out ARRAY of DICT_ENTRY<OBJPATH,ARRAY of
DICT_ENTRY<STRING,ARRAY of
DICT_ENTRY<STRING,VARIANT>>>
objpath_interfaces_and_properties
);
org.freedesktop.DBus.ObjectManager.InterfacesAdded(
OBJPATH object_path,
ARRAY of DICT_ENTRY<STRING,ARRAY of
DICT_ENTRY<STRING,VARIANT>> i
nterfaces_and_properties
);
org.freedesktop.DBus.ObjectManager.InterfacesRemoved(
OBJPATH object_path,
ARRAY<STRING> interfaces
);
D-Bus工具
dbus-send
dbus-send 发送消息
dbus-send [--system | --session] --type=TYPE --print-reply --dest=连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值
e.g.
dbus-send --session --type=method_call --print-reply --dest=连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值
dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.Introspectable.Introspect
dbus-send支持的参数类型包括:string, int32, uint32, double, byte, boolean。
Tips:如果是会话总线(session),不能在root用户下执行dbus-send命令
dbus-monitor
dbus-monitor监视通道上流动的消息
dbus-monitor [--system | --session | --address ADDRESS] [--profile | --monitor] [watch expressions]
e.g.
dbus-monitor "type='signal', sender='org.gnome.TypingMonitor', interface='org.gnome.TypingMonitor'"
Tips:不能在root用户下执行此命令
dbus-daemon
启动dbus-daemon的命令:(非root用户下)
DBUS_VERBOSE=1 dbus-daemon --session --print-address
dbus-daemon是有地址的,环境变量DBUS_SESSION_BUS_ADDRESS用于表示当前登录用户的session的dbus-daemon进程的地址,可以使用echo $DBUS_SESSION_BUS_ADDRESS
查看。
用自己启动的dbus-daemon转发消息:
- 启动一个dbus-daemon,输出如下:
xxxx@840-G7-PC:~$ DBUS_VERBOSE=1 dbus-daemon --session --print-address
unix:abstract=/tmp/dbus-dgsyNdddpv,guid=7d7666e25b903df290de42516569509f
- 用以下命令运行客户端、服务端程序
xxxx@840-G7-PC:~$ DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-dgsyNdddpv,guid=7d7666e25b903df290de42516569509f ./test_dbus_client
xxxx@840-G7-PC:~$ DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-dgsyNdddpv,guid=7d7666e25b903df290de42516569509f ./test_dbus_server
service
dbus中指的service是/usr/share/dbus-1/services 下的服务;
个人私自指定的服务也要放在此处。
D-Bus demo [1]
server端
#include <dbus/dbus.h>
#include <unistd.h>
#include <iostream>
void listen_signal(){
DBusMessage * msg;
DBusMessageIter arg;
DBusConnection * connection;
DBusError err;
//init dbus error
::dbus_error_init(&err);
//建立dbus连接 (session)
connection = ::dbus_bus_get(DBUS_BUS_SESSION, &err);
//给 连接名(Bus name) 分配一个方便记忆的名字:test.singal.dest,这个步骤不是必须的,但推荐这样处理
::dbus_bus_request_name(connection, "test.singal.dest",
DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
//通知D-Bus daemon,希望监听接口(test.signal.Type)的信号
::dbus_bus_add_match(connection,"type='signal', interface='test.signal.Type'",&err);
//实际需要发送东西给daemon来通知希望监听的内容,所以需要flush
::dbus_connection_flush(connection);
/*在循环中监听,每隔开1秒,就去自己的连接中获取这个信号。
这里给出的是连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。
我们也可以通过这个方式来获取method call消息。*/
while(1){
::dbus_connection_read_write(connection,0);
msg = ::dbus_connection_pop_message (connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg,"test.signal.Type","Test")){
if(!dbus_message_iter_init(msg,&arg))
fprintf(stderr,"MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg)!= DBUS_TYPE_STRING)
fprintf(stderr,"Param isnot string");
else
dbus_message_iter_get_basic(&arg,&sigvalue);
printf("Recetive Singal Value : %s\n",sigvalue);
}
dbus_message_unref(msg);
}//End of while
}
连接名 - Bus Name
唯一连接名 - unique connection name
当连接建立以后,D-Bus 服务会分配一个不可改变的连接名,称为唯一连接名(unique connection name),唯一连接名即使在进程结束后也不会再被其他进程所使用。唯一连接名以冒号开头,如“:34-907”。但唯一连接名总是临时分配,无法确定,也难以记忆,因此应用可以要求有另外一个名字公共名(well-known name)来对应唯一连接名。
client端
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
#include <unistd.h>
#include <iostream>
int send_a_signal(const char *sigvalue){
DBusError err;
DBusConnection * connection;
DBusMessage * msg;
DBusMessageIter arg;
dbus_uint32_t serial = 0;
//init dbus error
dbus_error_init(&err);
//建立dbus连接 (session)
connection = ::dbus_bus_get(DBUS_BUS_SESSION, &err);
/* 给 连接名 分配一个well-known的名字,这个步骤不是必须的,
可以用if 0来注释着一段代码,我们可以用这个名字来检查是否已经
开启了这个应用的另外的进程。*/
#if 1
::dbus_bus_request_name(connection, "test.singal.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 -1;
#endif
//发送一个信号, 给出这个信号的路径(即可以指向对象)、接口、信号名,创建一个Message
msg = ::dbus_message_new_signal("/test/signal/Object", "test.signal.Type", "Test");
if(msg == NULL){
fprintf(stderr,"MessageNULL\n");
return -1;
}
//给这个信号(Messge)具体的内容
::dbus_message_iter_init_append(msg, &arg);
bool ret = ::dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue);
if(!ret){
fprintf(stderr,"Out OfMemory!\n");
return -1;
}
printf("Signal Send: %s\n",sigvalue);
//将信号从连接中发送
bool res = ::dbus_connection_send(connection, msg, &serial);
if(!res){
fprintf(stderr,"Out of Memory!\n");
return -1;
}
::dbus_connection_flush(connection);
printf("--------Success Signal Send----------\n");
//释放相关的分配的内存。
::dbus_message_unref(msg);
return 0;
}