问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

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

发布网友 发布时间:2022-04-25 06:20

我来回答

1个回答

热心网友 时间:2022-04-08 02:04

  高效的利用dbus做client-server架构的方法
  在嵌入式系统中使用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_mole_name dbus_general.xml > general_stub.h
  dbus-binding-tool --mode=glib-client --prefix=your_mole_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_mole_name_methods[] = {
  { (GCallback) __client_request_cb, dbus_glib_marshal_your_mole_name_BOOLEAN__INT_INT_BOXED_POINTER_POINTER_POINTER_POINTER, 0 },
  };
  const DBusGObjectInfo dbus_glib_your_mole_name_object_info = {
  0,
  dbus_glib_your_mole_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传递消息/数据的效率,有什么更好的看法,欢迎交流。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
八月中国最凉快的地方 八月份哪里最凉快,去哪旅游好?美丽的地方 乱字同韵字是什么意思 华硕笔记本电脑触摸板怎么开笔记本电脑触摸板怎么开启和关闭_百度知 ... 陕西职务侵占案立案准则 结婚后我的恋情维系了十年,怎么做到的? 玉米仁子饭产自哪里 中国期货交易所的交易品种有哪些? 历史要怎么读,有啥诀窍 高中历史诀窍 ubuntu下怎么配置libdbus-glib环境, 能是下面程序编译通过 麻烦大哥们手把手教行吗?急……急…… 大众点评店铺的六大营销功能 为什么在Glade设置信号函数会失败?而手动在代码中通过gtk_signal_connect却可以呢? 大众点评为什么做开放平台? yum提示需要so文件 但是我编译好后还是那个错误 多谐振荡器工作时,两个三极管的工作状态是怎样的?发光二极管的亮与灭状态分别对应三极管的哪个工作状态 linux安装glib-2.38.0提示ffi.h: No such file or directory 中文版CPLD说明书 我的glib是2.34为什么安装pango时报错 WIFI精灵怎么卸载不了? 大众点评助力帮粘贴不了链接 怎样编译和配置GStreamer? ATF1508是什么?和EPM128SLC8有什么相似和差异? glib2.0/glib/giochannel.h请问这个枚举的用法怎么解释? 学好单片机与C语言对未来生活的重要性? 在大众点评怎么支持小伙伴 C语言中的g_free和free的区别,有没有网址可以查看到g_free的定义? ubuntu12.04下编译时报错:dbus&#47;dbus-glib.h:没有那个文件或目录,但是在&#47;usr&#47;include&#47;dbus-1.0&#47;dbus中有 大众点评暖心午餐为什么无法帮别人助力 Win7系统卸载腾讯电脑管家wifi共享精灵的方法? 电脑vga接口怎么插 vga线里面有几根线 我在安编译glib遇到这个问题怎么解决?gclosure.c:27:17: fatal error: ffi.h: No such file or directory VGA接口是什么样子的 linux glib\gtk的字符串相关问题 我在安装glib遇到这个问题怎么解决?gclosure.c:29:17: error: ffi.h: No such file or directory 针脚的VGA接口针脚 在头文件中含有#include &lt;gtk&#47;gtk.h&gt;,但在通过gcc编译时会有”gtk&#47;gtk.h,没有那个文件或目录”的提示,原 WebKit嵌入式移植 VGA是什么接口? 能否先测纯溶剂的流出时间再则溶液的流出时间 用VS2005怎么测试纯C++编写的程序? 物化问题 等压法是如何测量纯液体饱和蒸汽压的? 老师好!请问怎样用实验测定纯水中氢离子的物质的量浓度? 上海哪里可以测定纯水中二氧化硅含量? 如何用六维力传感器测纯力矩 或 如何通过纯力矩在某空间坐标系上的作用(即各轴方向力矩)计算出该纯力矩 小女孩的馒头柔软舒服用英语怎么说 女孩子过百岁都做什么馒头 女孩每天吃三四个馒头增重,为妈妈移植骨髓,懂事的孩子为何更让人心疼? 这个小女孩馒头和PP怎么样 给您的第一印象是什么,身材怎么样?好看吗?具体哪里好看?q