如何高效率的使用DBUS作client/server架构

原创 2007年12月07日 14:36:00


在嵌入式系统中使用dbus主要有两个方面的用途:
1:进程间通信
2:实现client/server模式;

2也是1的具体表现形式;

包括dbus自带的例子,都是采用dbus对数据的封装,实现client/server模式的,
缺点有二:
1 一个API要定义一个xml接口描述
2 数据封装非常复杂,非常不利于以后接口的扩展;

为了客服上面的缺点,提高可扩展性和效率,可以这样做:
如果一个应用分为client,server两端的话,要高效率的实现client/server之间
的通信,可以采用如下方式:


第一步:定义一个通用的API xml 接口描述,暂命令为dbus_general.xml

<?xml version="1.0" encoding="UTF-8" ?>
<node name="/org/freedesktop/DBus/General_api">
  <interface name="org.freedesktop.DBus.general_api">
    <method name="client_request">
      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="__client_request_cb"/>
      <arg type="i" name="action_id" direction="in" />   //这个地方就是不同API的ID
      <arg type="i" name="input_int" direction="in" />   //这个参数可以用,也可以不用
   <arg type="ay" name="input_garray" direction="in" />  //这个Garray用来从client传递数据,包括复杂的数据结构到server
   <arg type="i" name="outut_int" direction="out" />    //这个可以用,也可以不用
   <arg type="ay" name="output_garray" direction="out" /> //这个Garray用来从server侧传回数据到client侧
      <arg type="i" name="result" direction="out" />
    </method>
  </interface>
</node>

大家知道:在dbus文档中有这么的描述,

ay | Array of bytes | DBUS_TYPE_G_BYTE_ARRAY | GArray *  |g_array_free  

大家都不常用字节数组(GArray),大家常用的是integar,string等;
这个通用的模板关键之处就是这个Garray, Garray本身是个容器,这个
容器里面可以装任何东西。

我们就是利用这个GArray来实现client与server之间数据的传递,无论想传递
什么要的数据;


第二步:用dbus的工具函数生成stub/proxy头文件,这一步写到Makefile脚本中,以后不用修改了;

dbus-binding-tool --mode=glib-server --prefix=your_module_name dbus_general.xml > general_stub.h
dbus-binding-tool --mode=glib-client --prefix=your_module_name dbus_general.xml > general_proxy.h

生成的头文件,大家一般不要动它们,直接使用就可以了;

general_proxy.h:

.....
client_request (DBusGProxy *proxy, const gint IN_action_id, const gint IN_input_int, const GArray* IN_input_garray, gint* OUT_output_int, GArray** OUT_output_garray, gint* OUT_result, GError **error)

{
  return dbus_g_proxy_call (proxy, "request", error, G_TYPE_INT, IN_action_id, G_TYPE_INT, IN_input_int, dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), IN_input_garray, G_TYPE_INVALID, G_TYPE_INT, OUT_output_int, dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), OUT_output_garray, G_TYPE_INT, OUT_result, G_TYPE_INVALID);
}
.....

general_stub.h:
.....

#include <dbus/dbus-glib.h>
static const DBusGMethodInfo dbus_glib_your_module_name_methods[] = {
  { (GCallback) __client_request_cb, dbus_glib_marshal_your_module_name_BOOLEAN__INT_INT_BOXED_POINTER_POINTER_POINTER_POINTER, 0 },
};

const DBusGObjectInfo dbus_glib_your_module_name_object_info = {
  0,
  dbus_glib_your_module_name_methods,
  1,
"org.freedesktop.DBus.general_api/0client_request/0S/0action_id/0I/0i/0input_int/0I/0i/0input_garray/0I/0ay/0output_int/0O/0F/0N/0i/0output_garray/0O/0F/0N/0ay/0result/0O/0F/0N/0i/0/0/0",
"/0",
"/0"
};
......

第三步:实现client侧,主要是直接调用general_proxy.h的接口函数client_request(),用GArray传入你的数组(可以携带任何你自己定义的数据结构)

gboolean proxy_func1 (void)
{
 int api_id = 0;      //这个在不同的proxy_func里面可以有不同的值,主要是区分函数作用
 GArray* in_array = NULL;
 GArray* out_array = NULL; //在这里不用分配内存,放在server侧做内存分配
 
 in_array = g_array_new(FALSE, FALSE, sizeof(guint8));
 if (!in_array)
  return FALSE;
  
 //把你自己的数据封装到in_array中,假设你的数据结构是your_strcut_t
 
 your_struct_t my_own_data;
 
 //fill my_own_data
 ...
 
 //放到in_array中,这很关键
 g_array_append_vals(in_array, my_own_data, sizeof(your_strcut_t));  
 
 //调用general_proxy.h中的dbus接口
 client_request(dbus_proxy, api_id, in_array, &out_array, .....); //通过dbus把数据从到server侧,server侧如何处理,看第四步;
 
 //当sever返回数据后,从out_array中取出来就可以了
 your_strcut_t* g_array_data = (your_strcut_t*)out_array->data;
 .....
 
 //free
 if (in_array)
  g_free (in_array);
 
 if (out_array)
  g_free (out_array);
  
 ....


第四步:实现Server侧,主要是实现general_stub.h中的函数__client_request_cb();

//这个函数的参数很长,除了第一个参数是server对象外,其余的参数可以直接从
general_proxy.h对应的接口参数拷贝过来;应该这个函数和proxy的接口是一对!

gboolean
__client_request_cb (ServerObject *server_object, const gint IN_action_id, const gint IN_input_int, const GArray* IN_input_garray, gint* OUT_output_int, GArray** OUT_output_garray, gint* OUT_result, GError **error)
{
 *OUT_output_garray = g_array_new(FALSE, FALSE, sizeof(guint8));//在client侧没有分配内存,server这里一定要分配
 
 //卸下client侧传递过来的数据
 your_strcut_t ×p_data= (your_strcut_t *)&g_array_index(input_garray,your_strcut_t, 0);
 
 //对卸下的数据进行处理,看你的程序做什么功能了:)
 .....
 .....
 
 //如果要传回数据到client侧,假设处理过的数据为:your_strcut_t dealed_with_data
 g_array_append_vals(*output_garray, &dealed_with_data, sizeof(your_strcut_t));
 
 
 return TRUE;//一定要返回TRUE,否则client侧收不到数据的;
 
}


上述通用步骤中,1,2在今后的扩展中,是不要要改的,尤其是第一步,dbus的xml接口描述非常
麻烦;如果为每个API自己去定义xml接口描述,搞不好,client和server之间不通;而且,一段时间
后,不看dbus的文档,就会忘记如何写其xml接口;所以做个通用的xml接口描述很省事;

3,4是client/server侧的各自实现,结构是钉死的,不用改多少;一个函数如此,N个函数也是这样;
如果你有30个函数,要分别实现它们吗?不必要,只要给各自的函数定义其ID就行;
在client/server侧的函数里面搞个switch-case结构就分开了;

架构定好了,传递数据也非常方便,比dbus自己的dbus_g_type_struct_set效率高的多,目前开源软件
多用dbus_g_type_struct_set,效率很低,对于传递批量数据,效率很低;

如果大家对于如何提高dbus传递消息/数据的效率,有什么更好的看法,欢迎交流。


参考:
一位网友写的dbus的基础的使用,写的不错,大家可以参考:
http://blog.csdn.net/yuhang111/archive/2007/08/27/1760141.aspx

另外,dbus的根源在:
http://www.freedesktop.org/wiki/Software/dbus,这里是dbus project的宿主地址,
其官方文档都在这里,大家有空看看;


 

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Archive for the Linux Category --Dbus study

Archive for the Linux Category来自: http://www.robotercoding.com/blog/?cat=3 « Previous EntriesAug 20 ...

如何高效的利用dbus做client-server架构

在嵌入式系统中利用dbus重要有两个方面的用处: 1:历程间通信 2:告终client/server形式; 2也是1的翔实出现形式; 包括dbus自带的例子,都是批准dbus对数据的封...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

asp.net(C#)海量数据表高效率分页算法(易懂,不使用存储过程)

首先创建一张表(要求ID自动编号): createtableredheadedfile( idintidentity(1,1), filenamesnvarchar(20), sendusern...

Android高效率实现win8进度条效果,手把手教会你实现效果,项目中直接使用

转载请注明出处:http://blog.csdn.net/jakeyangchina/article/details/54413523 新的一年新的开始,2017年争取每个星期至少一篇技术博客,方便...

高效率的使用VIM

虽然从很久前就开始用 VIM 了,但一直都是半调吊子,翻来覆去只用自己会的命令。最近为了提高书写代码的效率,还有 coding 时候的乐趣,又重新钻研了一下 VIM,发现了一篇很好的 VIM 入门...

mysql使用rand随机查询记录的高效率方法

一直以为mysql随机查询几条数据,就用   SELECT * FROM `table` ORDER BY RAND() LIMIT 5    就可以了。   但是真正测试一下才发现这...

StringBuffer和Vector的高效率使用

Java使得复杂应用的开发变得相对简单,毫无疑问,它的这种易用性对Java的大范围流行功不可没。然而,这种易用性实际上是一把双刃剑。一个设计良好的Java程序,性能表现往往不如一个同样设计良好的C++...

高效率的使用VIM

虽然从很久前就开始用 VIM 了,但一直都是半调吊子,翻来覆去只用自己会的命令。最近为了提高书写代码的效率,还有 coding 时候的乐趣,又重新钻研了一下 VIM,发现了一篇很好的 VIM 入门的文...

mysql使用rand随机查询记录的高效率方法

一直以为mysql随机查询几条数据,就用    SELECT * FROM `table` ORDER BY RAND() LIMIT 5      就可以了。    但是真正测试一下才发现这...
  • zqtsx
  • zqtsx
  • 2013-10-14 18:18
  • 1444

Android高效率实现广告图片循环播放,手把手教会你实现效果,项目中直接使用

转载请注明出处:http://blog.csdn.net/jakeyangchina/article/details/53691436好多app上都会看到广告图片无限制的循环播放,今天带大家一步步实现...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)