关闭

D-bus —— 进程间通讯

标签: 通讯listexception桌面环境nullsoap
786人阅读 评论(0) 收藏 举报
分类:
1. 简介

通常一个桌面中会有几个不同的程序同时运行,而且它们之间需要相互间进行通讯。在操作系统层,这些不同的程序用不同的进程来实现。而为了安全起见,不同进 程间是不能直接相互调用和内存访问的,也就是一个进程对另外的进程是不可见的。这就需要一个机制来定义一个接口,一个进程通过接口访问另外一个进程,对于 发起访问的进程来说,调用 IPC 接口中的函数与调用自己进程内的函数是没有区别的这就是进程间通讯。进程间通讯有许多不同的实现:D-bus,CORBA,KDE 中的 DCOP 和 Gnome 中的 Bonobo 等。

实践证明, D-bus 是未来一段时间的桌面程序间进行通讯的主要方式。 D-BUS 的目标是将 DCOP 和 Bonobo 替换为简单的 IPC,并集成这两种桌面环境。由于尽可能地减少了 D-BUS 所需的依赖,所以其他可能会使用 D-BUS 的应用程序不用担心引入过多依赖。

2. 与其它通讯方式的对比


其他方式的缺点概括起来就是:

CORBA:
非常复杂,难于实现。看起来接口定义得相当完善,所以 Gnome 和 KDE 都曾经试图用它作为 进程间通讯的方式。但是因为此方式的接口复杂难用,速度慢,耗内存等缺点,结果都以失败告终。

 DCOP:轻量级,依赖于 QT,曾经是 KDE 中的默认进程间通信方式,而目前KDE4 已经完全转移到 Dbus;

Bonobo:基于CORBA,实现复杂,依赖于GObject。目前Gnome 除了极个别的复杂情况下仍然使用 Bonobo 外,大部分已经转移到 D-Bus。

XML-RPC 和 SOAP:所有消息都以复杂的 XML 格式封包,用文本模式发送,接收后再转换回二进制模式。两次转换低效而耗时、

COM/DCOM: 微软早期版本使用,而且只能在微软的视窗系统中使用。众所周知,微软的设计通常包含安全问题,曾经风靡一时的冲击波病毒就是利用了远程进程间调用的漏洞。 COM 当然也不例外,ActiveX 依然是大部分网页病毒的源泉。COM+解决了部分问题,不过也实在好不到哪里去。


综合起来,大部分的缺点包括:

(1)有些过于复杂,不适合桌面使用

(2)有些严重依赖桌面环境,只能在 Gnome 中通讯或只能在 KDE 中通讯。这就造成 Gnome 和 KDE 间的程序难以相互通讯,扩大了 Linux 桌面的分裂。

3. Dbus 的特点


Dbus 的设计重复考虑了以上缺点,其主要特点包括:

(1)基于消息的通讯方式,使用二进制传输数据,使得实现起来相对简单,效率高

(2) 独立于 Gnome 和 KDE,在 freedesktop.org 的维护下发展。这样 Gnome 和 KDE 的程序之间就可以进行良好的通讯。

(3)正如其名字显示的那样,Dbus 使用总线系统,这样一个进程就可以同时和一组进程进行通讯。Dbus 中可以使用系统级总线,操作系统可以像总线中发送消息,供用户空间的程序使用。将整个桌面系统更好的整合起来。

(4)典型的 D-BUS 设置将由几个总线构成,经常使用系统总线和会话总线。一个持久系统总线在引导时就会启动,由操作系统和后台进程使用,安全性非常好,应用程序无法欺骗系统事件。会话总线在用户登录后启动,为用户私有,供用户的自己的应用程序进行通信。

4. dbus 的调用方式


下面这个例子来自 Dbus 的官方教程,使用了 D-Bus 的 GLib 绑定,展示了如何通过 dbus 调用函数,更详细的例子请参考 http://dbus.freedesktop.org/doc/dbus/libdbus-tutorial.html

int
main (int argc, char **argv)
{
  DBusGConnection *connection;
  GError *error;
  DBusGProxy *proxy;
  char **name_list;
  char **name_list_ptr;
  
  g_type_init ();

  error = NULL;
  
  /* 首先连接到总线 */
  connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
  if (connection == NULL)
    {
      g_printerr ("Failed to open connection to bus: %s\n",
                  error->message);
      g_error_free (error);
      exit (1);
    }

  /* 创建代理对象 "bus driver" (name "org.freedesktop.DBus") */
  
  proxy = dbus_g_proxy_new_for_name (connection,
                                     DBUS_SERVICE_DBUS,
                                     DBUS_PATH_DBUS,
                                     DBUS_INTERFACE_DBUS);

  /* 跨进程调用 ListNames 方法 并等待相应 */
  error = NULL;
  if (!dbus_g_proxy_call (proxy, "ListNames", &error, G_TYPE_INVALID,
                          G_TYPE_STRV, &name_list, G_TYPE_INVALID))
    {
      /* 演示远程异常与本地错误的处理 */
      if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
        g_printerr ("Caught remote method exception %s: %s",
             dbus_g_error_get_name (error),
             error->message);
      else
        g_printerr ("Error: %s\n", error->message);
      g_error_free (error);
      exit (1);
    }

  /* 打印结果 */
 
  g_print ("Names on the message bus:\n");
  
  for (name_list_ptr = name_list; *name_list_ptr; name_list_ptr++)
    {
      g_print ("  %s\n", *name_list_ptr);
    }
  g_strfreev (name_list);

  /* 释放接口 */
  g_object_unref (proxy);

  return 0;
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1715000次
    • 积分:19706
    • 等级:
    • 排名:第436名
    • 原创:27篇
    • 转载:1525篇
    • 译文:2篇
    • 评论:128条
    最新评论