Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4250400
  • 博文数量: 776
  • 博客积分: 13014
  • 博客等级: 上将
  • 技术积分: 10391
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-22 17:00
文章分类

全部博文(776)

文章存档

2015年(55)

2014年(43)

2013年(147)

2012年(20)

2011年(82)

2010年(429)

分类: LINUX

2010-02-27 16:35:45

典型的桌面都会有多个应用程序在运行,而且,它们经常需要彼此进行通信。DCOP是一个用于KDE的解决方案,但是它依赖于Qt,所以不能用于其他桌面环境之中。类似的,Bonobo是一个用于GNOME的解决方案,但是非常笨重,因为它是基于 CORBA的。它还依赖于GObject,所以也不能用于GNOME之外。 D-BUS的目标是将DCOP和Bonobo替换为简单的IPC,并集成这两种桌面环境。由于尽可能地减少了D-BUS所需的依赖,所以其他可能会使用 D-BUS的应用程序不用担心引入过多依赖。

  D-BUS属于FreeDesktop.org项目的一部分。
守护进程,没有使用常用的二进制字节流,而是使用了二进制消息的概念,消息由消息头和相应的数据组成。

  操作系统的概念: 包括内核、系统守护进程和进程。D-BUS的设计目的:方便同一个桌面会话中的多个应用程序之间的通信;有助于桌面应用程序和操作系统之间的通信。专门用于桌面的,可能不适用于其他方面的应用。

  D-BUS总线分类:系统总线和会话总线。

  持久的系统总线(system bus),它在引导时就会启动。这个总线由操作系统和后台进程使用,安全性非常好,以使得任意的应用程序不能欺骗系统事件。

  还将有很多会话总线(session buses),这些总线当用户登录后启动,属于那个用户私有。它是用户的应用程序用来通信的一个会话总线。当然,如果一个应用程序需要接收来自系统总线的消息,它不如直接连接到系统总线----不过,它可以发送的消息将是受限的。

  D-BUS基础

  API没有绑定到任何一个特定的语言或框架。例如有Glib/Qt/python/C#的D-Bus绑定。

  使用D-BUS发送一个消息到总线 #include //要使用dbus则必须包含此文件

  #include

  #include /*

  cc $(pkg-config --cflags --libs dbus-glib-1) -o dbus-send-hello dbus-send-hello.c && ./dbus-send-hello

  */

  int main (int argc, char *argv[])

  {

  DBusError dberr;

  DBusConnection *dbconn;

  DBusMessage *dbmsg;

  char *text;

  dbus_error_init (&dberr);

  dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr); //代表连接到会话总线,如果需要连接到

  //系统总线,简单把DBUS_BUS_SESSION替换为DBUS_BUS_SYSTEM即可。但是有麻烦,因为

  //系统总线对可以连接到它的用户有限制。可能需要提供一个.service文件指明能连接到某一个指定服务器的权限

  if (dbus_error_is_set (&dberr)) {

  fprintf (stderr, "getting session bus failed: %s\n", dberr.message);

  dbus_error_free (&dberr);

  return EXIT_FAILURE;

  }

  dbmsg = dbus_message_new_signal ("/com/wiley/test",

  "com.wiley.test",

  "TestSignal");

  /* 函数原型是

  DBusMessage* dbus_message_new_signal (const char *path,

  const char *interface,

  const char *name) */

  if (dbmsg == NULL) {

  fprintf (stderr, "Could not create a new signal\n");

  return EXIT_FAILURE;

  }

  text = "Hello World";

  dbus_message_append_args (dbmsg, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);

  dbus_connection_send (dbconn, dbmsg, NULL);

  printf ("Sending signal to D-Bus\n");

  dbus_message_unref (dbmsg);

  dbus_connection_unref (dbconn);

  return EXIT_SUCCESS;

  }

  #include //要使用dbus则必须包含此文件 #include #include /* cc $(pkg-config --cflags --libs dbus-glib-1) -o dbus-send-hello dbus-send-hello.c && ./dbus-send-hello */ int main (int argc, char *argv[]) { DBusError dberr; DBusConnection *dbconn; DBusMessage *dbmsg; char *text; dbus_error_init (&dberr); dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr); //代表连接到会话总线,如果需要连接到 //系统总线,简单把DBUS_BUS_SESSION替换为DBUS_BUS_SYSTEM即可。但是有麻烦,因为 //系统总线对可以连接到它的用户有限制。可能需要提供一个.service文件指明能连接到某一个指定服务器的权限 if (dbus_error_is_set (&dberr)) { fprintf (stderr, "getting session bus failed: %s\n", dberr.message); dbus_error_free (&dberr); return EXIT_FAILURE; } dbmsg = dbus_message_new_signal ("/com/wiley/test", "com.wiley.test", "TestSignal"); /* 函数原型是 DBusMessage* dbus_message_new_signal (const char *path, const char *interface, const char *name) */ if (dbmsg == NULL) { fprintf (stderr, "Could not create a new signal\n"); return EXIT_FAILURE; } text = "Hello World"; dbus_message_append_args (dbmsg, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID); dbus_connection_send (dbconn, dbmsg, NULL); printf ("Sending signal to D-Bus\n"); dbus_message_unref (dbmsg); dbus_connection_unref (dbconn); return EXIT_SUCCESS; }

  DBus是与应用程序中的对象而不是应用程序自身进行通信。在GLIB应用程序中,意味着是与GObject及其派生对象通信。应用程序中,这些对象以应用程序地址空间中内存地址的形式传递,将这些内存地址传递给其他应用程序是没有意义的。D-BUS传递对象路径,对象路径类似于文件系统路径,例如 /org/foo/bar等表示Foo Bar应用程序的顶层对象路径。并不是必需的,但是这样做可以避免产生冲突。

  发送给一个对象的消息类型:

  方法调用(method calls)、方法返回(method returns)、信号(signals) 和错误(errors)。

  要执行 D-BUS 对象的方法,您需要向对象发送一个方法调用消息。它将完成一些处理并返回一个方法返回消息或者错误消息。信号的不同之处在于它们不返回任何内容:既没有“信号返回”消息,也没有任何类型的错误消息。

  dbus_int32_t v_INT32 = 42;

  const char *v_STRING = "Hello World";

  dbus_message_append_args (message,

  DBUS_TYPE_INT32, &v_INT32,

  DBUS_TYPE_STRING, &v_STRING,

  DBUS_TYPE_INVALID);

  const dbus_int32_t array[] = { 1, 2, 3 };

  const dbus_int32_t *v_ARRAY = array;

  dbus_message_append_args (message,

  DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3,

  DBUS_TYPE_INVALID);

   dbus-get-hello.c : #include

  #include

  #include /*

  cc $(pkg-config --cflags --libs dbus-glib-1) -o dbus-get-hello dbus-get-hello.c && ./dbus-get-hello

  */

  static DBusHandlerResult

  filter_func (DBusConnection *connection,

  DBusMessage *message,

  void *user_data)

  {

  dbus_bool_t handled = FALSE;

  char *signal_text = NULL;

  if (dbus_message_is_signal (message, "com.wiley.test", "TestSignal")) {

  DBusError dberr;

  dbus_error_init (&dberr);

  dbus_message_get_args (message, &dberr, DBUS_TYPE_STRING, &signal_text, DBUS_TYPE_INVALID);

  if (dbus_error_is_set (&dberr)) {

  fprintf (stderr, "Error getting message args: %s", dberr.message);

  dbus_error_free (&dberr);

  } else {

  DBusConnection *dbconn = (DBusConnection*) user_data;

  printf ("Received TestSignal with value of: '%s'\n", signal_text);

  handled = TRUE;

  }

  }

  return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);

  }

  int main (int argc, char *argv[])

  {

  DBusError dberr;

  DBusConnection *dbconn;

  dbus_error_init (&dberr);

  dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr);

  if (dbus_error_is_set (&dberr)) {

  fprintf (stderr, "getting session bus failed: %s\n", dberr.message);

  dbus_error_free (&dberr);

  return EXIT_FAILURE;

  }

  dbus_bus_request_name (dbconn, "com.wiley.test",

  DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);

  if (dbus_error_is_set (&dberr)) {

  fprintf (stderr, "requesting name failed: %s\n", dberr.message);

  dbus_error_free (&dberr);

  return EXIT_FAILURE;

  }

  if (!dbus_connection_add_filter (dbconn, filter_func, NULL, NULL))

  return EXIT_FAILURE;

  dbus_bus_add_match (dbconn,

  "type='signal',interface='com.wiley.test'",

  &dberr);

  if (dbus_error_is_set (&dberr)) {

  fprintf (stderr, "Could not match: %s", dberr.message);

  dbus_error_free (&dberr);

  return EXIT_FAILURE;

  }

  while (dbus_connection_read_write_dispatch (dbconn, -1))

  ; /* empty loop body */

  return EXIT_SUCCESS;

  }

  #include #include #include /* cc $(pkg-config --cflags --libs dbus-glib-1) -o dbus-get-hello dbus-get-hello.c && ./dbus-get-hello */ static DBusHandlerResult filter_func (DBusConnection *connection, DBusMessage *message, void *user_data) { dbus_bool_t handled = FALSE; char *signal_text = NULL; if (dbus_message_is_signal (message, "com.wiley.test", "TestSignal")) { DBusError dberr; dbus_error_init (&dberr); dbus_message_get_args (message, &dberr, DBUS_TYPE_STRING, &signal_text, DBUS_TYPE_INVALID); if (dbus_error_is_set (&dberr)) { fprintf (stderr, "Error getting message args: %s", dberr.message); dbus_error_free (&dberr); } else { DBusConnection *dbconn = (DBusConnection*) user_data; printf ("Received TestSignal with value of: '%s'\n", signal_text); handled = TRUE; } } return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); } int main (int argc, char *argv[]) { DBusError dberr; DBusConnection *dbconn; dbus_error_init (&dberr); dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr); if (dbus_error_is_set (&dberr)) { fprintf (stderr, "getting session bus failed: %s\n", dberr.message); dbus_error_free (&dberr); return EXIT_FAILURE; } dbus_bus_request_name (dbconn, "com.wiley.test", DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr); if (dbus_error_is_set (&dberr)) { fprintf (stderr, "requesting name failed: %s\n", dberr.message); dbus_error_free (&dberr); return EXIT_FAILURE; } if (!dbus_connection_add_filter (dbconn, filter_func, NULL, NULL)) return EXIT_FAILURE; dbus_bus_add_match (dbconn, "type='signal',interface='com.wiley.test'", &dberr); if (dbus_error_is_set (&dberr)) { fprintf (stderr, "Could not match: %s", dberr.message); dbus_error_free (&dberr); return EXIT_FAILURE; } while (dbus_connection_read_write_dispatch (dbconn, -1)) ; /* empty loop body */ return EXIT_SUCCESS; }

  为了确保正确地接受到信号,我们必须确认拥有com.wiley.test命名空间:

  dbus_bus_request_name (dbconn, "com.wiley.test",DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);

  注册过滤函数:

  dbus_bool_t dbus_connection_add_filter ( DBusConnection * connection,

  DBusHandleMessageFunction
,

  void * user_data,

  DBusFreeFunction free_data_function

  )

  // connection the connection

  // function function to handle messages

  // user_data user data to pass to the function

  // free_data_function function to use for freeing user data

  //Adds a message filter.

  if (!dbus_connection_add_filter (dbconn, filter_func, NULL, NULL))

  return EXIT_FAILURE;

  dbus_bool_t dbus_connection_add_filter ( DBusConnection * connection, DBusHandleMessageFunction function, void * user_data, DBusFreeFunction free_data_function ) // connection the connection // function function to handle messages // user_data user data to pass to the function // free_data_function function to use for freeing user data //Adds a message filter. if (!dbus_connection_add_filter (dbconn, filter_func, NULL, NULL)) return EXIT_FAILURE;

  确保信号不会被忽略,因为通过总线发送的信号有很多,并非所有的应用程序都对它们感兴趣,所以默认情况下,信号将被忽略以阻止“信号泛滥”。

  一直监听的代码: 过滤函数的实现: dbus_bool_t dbus_connection_read_write_dispatch ( DBusConnection * connection,

  int timeout_milliseconds

  )

  //This function is intended for use with applications that don't want to //write a main loop and deal with DBusWatch and DBusTimeout.

  // An example usage would be:

  while (dbus_connection_read_write_dispatch (connection, -1))

  ; // empty loop body

  


Ad_info
阅读(3067) | 评论(0) | 转发(0) |
0

上一篇:dbus精简IPC实例

下一篇:use thedbus c API

给主人留下些什么吧!~~