1目的

对比进程间通讯方法,选择适宜平台开发的进程间通讯方式。

若果是开源模块的话,重点考察通讯机制,插口封装程度,稳定性,使用是否简易。

2Linux常用的进程通讯方法简介2.1管线

管线(Pipe)及有名管线(namedpipe):管线可用于具有亲缘关系进程间的通讯,有名管线克服了管线没有名子的限制,因而,除具有管线所具有的功能外,它还容许无亲缘关系进程间的通讯;

2.2讯号

讯号(Signal):讯号是比较复杂的通讯方法,用于通知接受进程有某种风波发生,不仅用于进程间通讯外,进程还可以发送讯号给进程本身;linux不仅支持Unix初期讯号语义函数sigal外linux环境进程间通信,还支持语义符合Posix.1标准的讯号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠讯号机制,又能否统一对外插口,用sigaction函数重新实现了signal函数);

2.3报文

报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列systemV消息队列。有足够权限的进程可以向队列中添加消息,被赋于读权限的进程则可以读走队列中的消息。消息队列克服了讯号承载信息量少,管线只能承载无格式字节流以及缓冲区大小受限等缺点。

2.4共享显存

共享显存:致使多个进程可以访问同一块显存空间,是最快的可用IPC方式。是针对其他通讯机制运行效率较低而设计的。常常与其它通讯机制,如讯号量结合使用,来达到进程间的同步及互斥。

2.5讯号量

讯号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。

2.6Socket

套插口(Socket):更为通常的进程间通讯机制,可用于不同机器之间的进程间通讯。原本是由Unix的BSD分支开发下来的,但现今通常可以移植到其它类Unix系统上:Linux和SystemV的变种都支持套接字。

2.7小结

此处只是简单介绍了Linux内核提供的进程间通讯的方法,具体使用方式可以参照《linux环境进程间通讯(全)》

附件:

3D-bus简介3.1主要作用

1.在同一个桌面会话中,进行桌面应用程序之间的通信

2.桌面程序与内核或则守护进程的通讯。

3.2进程通讯体系

它有以下几层:

1.libdbus库,提供给各个应用程序调用,使应用程序具有通讯和数据交换的能力,两个应用程序可以直接进行通讯,如同是一条socket通道,两个程序之间构建通道以后,就可以通信了。

2.消息守护进程,在libdbus的基础上创建,可以管理多个应用程序之间的通讯。每位应用程序都和消息守护进程构建dbus的链接,之后由消息守护进程进行消息的分派。

3.各类包装库linux环境进程间通信,有libdbus-glib,libdbus-qt等等,目的是将dbus的底层api进行一下封装。

在DBus的体系中,有一个常驻的进程Daemon,所有进程间的交互都通过它来进行分发和管理。所有希望使用DBus进行通讯的进程,都必须事先连上Daemon,并将自己的名子注册到Daemon上,然后,Daemon会依照须要把消息以及数据发到相应的进程中。

3.3机制简介

D-Bus机制的重要概念有以下几个:

a)对象:对象是封装后的匹配器与反弹函数,它以对等(peer-to-peer)合同使每位消息都有一个源地址和一个目的地址。这种地址又称为对象路径,或则称之为总线名称。对象的插口是反弹函数,它以类似C++的虚拟函数实现。当一个进程注册到某个总线时,都要创建相应的消息对象。

b)消息:D-Bus的消息分为讯号(signals)、方法调用(methodcalls)、方法返回(methodreturns)和错误(errors)。讯号是最基本的消息,注册的进程可简单地发送讯号到总线上红帽linux系统下载,其他进程通过总线读取消息。方式调用是通过总线传递参数,执行另一个进程插口函数的机制,用于某个进程控制另一个进程。方式返回是注册的进程在收到相关信息后,手动作出反应的机制,由反弹函数实现。错误是信号的一种,是注册进程错误处理机制之一。

c)服务:服务(Services)是进程注册的具象。进程注册某个地址后,即可获得对应总线的服务。D-Bus提供了服务查询插口,进程可通过该插口查询某个服务是否存在。或则在服务结束时手动收到来自系统的消息。

D-Bus机制描述:

a)D-Bus具备自身的合同,合同基于二补码数据设计,与数据结构和编码形式无关。该合同无需对数据进行序列化,保证了信息传递的高效性。无论是libdbus,还是D-Bus总线守护进程,均不须要太大的系统开支。

b)D-Bus本身是建立在Socket机制之上。真正的通讯还是由Socket来完成的。DBus则是在这之上,拟定了一些通讯的合同,并提供了更初一层的插口,以更便捷应用程序之间进行数据的交互。

c)总线是D-Bus的进程间通讯机制,一个系统中一般存在多条总线,这种总线由D-Bus总线守护进程管理。最重要的总线为系统总线(SystemBus),Linux内核引导时,该总线就已被放入显存。只有Linux内核、Linux桌面环境和权限较高的程序能够向该总线写入消息,借此保障系统安全性,避免有恶意进程冒充Linux发送消息。会话总线(SessionBuses)由普通进程创建,可同时存在多条。会话总线属于某个进程私有,它用于进程间传递消息。

D-Bus通讯流程描述:

l方式调用的通常流程:

1.使用不同语言绑定的dbus高层插口,都提供了一些代理对象,调用其他进程上面的远端对象如同是在本地进程中的调用一样。应用调用代理上的技巧ubuntu linux,代理将构造一个方式调用消息给远端的进程。

2.在DBUS的底层插口中,应用须要自己构造方式调用消息(methodcallmessage),而不能使用代理。

3.方式调用消息上面的内容有:目的进程的busname,技巧的名子,技巧的参数,目的进程的对象路径,以及可选的插口名称。

4.方式调用消息是发送到busdaemon中的。

5.busdaemon查找目标的busname,假若找到,就把这个方式发送到该进程中,否则,daemon会形成错误消息,作为应答消息给发送进程。

6.目标进程解开消息,在dbus底层插口中,会立刻调用方式,之后发送方式的应答消息给daemon。在dbus高层插口中,会先检查对象路径,插口,技巧名称,之后把它转换成对应的对象(如GObject,QT中的QObject等)的方式,之后再将应答结果转换成应答消息发给daemon。

7.busdaemon接受到应答消息,将把应答消息直接发给发出调用消息的进程。

8.应答消息中可以宽容好多返回值,也可以标示一个错误发生,当使用绑定时,应答消息将转换为代理对象的返回值,或则步入异常。

busdaemon不对消息重新排序,假如发送了两条消息到同一个进程,她们将根据发送次序接受到。接受进程并须要依照次序发出应答消息,比如在多线程中处理那些消息,应答消息的发出是没有次序的。消息都有一个序列号可以与应答消息进行配对。

l讯号的通常流程如下:

1.当使用dbus底层插口时,讯号须要应用自己创建和发送到daemon,使用dbus高层插口时,可以使用相关对象进行发送,如Glib上面提供的讯号触发机制。

2.讯号包含的内容有:讯号的插口名称,讯号名称,发送进程的busname,以及其他参数。

3.任何进程都可以根据”matchrules”注册相关的讯号,daemon有一张注册的列表。

4.daemon测量讯号,决定什么进程对这个讯号感兴趣,之后把讯号发送给这种进程。

5.每位进程收到讯号后,假如是使用了dbus高层插口,可以选择触发代理对象上的讯号。假如是dbus底层插口,须要检测发送者名称和讯号名称,之后决定如何做。

3.4基于Glib的样例3.4.1对比Glib的类型说明

dbus和glib的数据类型映射如下:

D-Busbasictype

GType

Freefunction

Notes

BYTE

G_TYPE_UCHAR

BOOLEAN

G_TYPE_BOOLEAN

INT16

G_TYPE_INT

WillbechangedtoaG_TYPE_INT16once

GLibhasit

UINT16

G_TYPE_UINT

WillbechangedtoaG_TYPE_UINT16once

GLibhasit

INT32

G_TYPE_INT

WillbechangedtoaG_TYPE_INT32once

GLibhasit

UINT32

G_TYPE_UINT

WillbechangedtoaG_TYPE_UINT32once

GLibhasit

INT64

G_TYPE_GINT64

UINT64

G_TYPE_GUINT64

DOUBLE

G_TYPE_DOUBLE

STRING

G_TYPE_STRING

g_free

OBJECT_PATH

DBUS_TYPE_G_PROXY

g_object_unref

Thereturnedproxydoesnothaveaninterfaceset;use

dbus_g_proxy_set_interfacetoinvokemethods

Containertypemappings

dbus数据也有宽容器类型,像DBUS_TYPE_ARRAY和DBUS_TYPE_STRUCT,dbus的数据类型可以是嵌套的,如有一个链表,内容是字符串的字段集合。

然而,并不是所有的类型都有普通的使用,DBUS_TYPE_STRUCT应当可以宽容非基本类型的数据类型。glib绑定尝试使用比较显著的形式进行申明。

D-Bustypesignature

Description

GType

Ctypedef

Freefunction

Notes

as

Arrayofstrings

G_TYPE_STRV

char**

g_strfreev

Genericvaluecontainer

G_TYPE_VALUE

GValue*

g_value_unset

Thecallingconventionsforvaluesexpectthatmethodcallershave

allocatedreturnvalues;seebelow.

同时定义了新的字段类型集合。

D-Bustypesignature

Description

GType

Ctypedef

Freefunction

Notes

ay

Arrayofbytes

DBUS_TYPE_G_BYTE_ARRAY

GArray*

g_array_free

au

Arrayofuint

DBUS_TYPE_G_UINT_ARRAY

GArray*

g_array_free

ai

Arrayofint

DBUS_TYPE_G_INT_ARRAY

GArray*

g_array_free

ax

Arrayofint64

linux环境进程间通信_linux环境进程间通信_linux环境进程间通信

DBUS_TYPE_G_INT64_ARRAY

GArray*

g_array_free

at

Arrayofuint64

DBUS_TYPE_G_UINT64_ARRAY

GArray*

g_array_free

ad

Arrayofdouble

DBUS_TYPE_G_DOUBLE_ARRAY

GArray*

g_array_free

ab

Arrayofboolean

DBUS_TYPE_G_BOOLEAN_ARRAY

GArray*

g_array_free

定义了字典类型

D-Bustypesignature

Description

GType

Ctypedef

Freefunction

Notes

a{ss}

Dictionarymappingstringstostrings

DBUS_TYPE_G_STRING_STRING_HASHTABLE

GHashTable*

g_hash_table_destroy

3.4.2使用样例

l网上有一个叫d-feet的python程序,我们可以用它来观察系统中的dbus世界。

图1、由d-feet观察到的D-Bus世界

D-Bus是一个程序。它提供了API。但我们通常不会直接使用dbus的插口。dbus-glib是GTK版本的dbus插口封装。本文假定读者安装了dbus-glib,我安装的是dbus-glib-0.76。旁边都会看见,通过python操纵dbus是多么简单。

l以hello-dbus3-0.1.tar.gz为例(附表有原事例链接),这是一个autotool工程,你们解包后,执行:

./autogen.sh

./configure

make

之后在src目录运行:

./example-service

这时再运行d-feet,联接sessionbus,在“BusName”窗口会见到一个叫“org.fmddlmyy.Test”连接名。

图2、提供D-Bus服务的org.fmddlmyy.Test

选择“org.fmddlmyy.Test”,在左边窗口点击展开“ObjectPaths”->“/TestObj”->“Interfaces”->“org.fmddlmyy.Test.Basic”->“Methods”,可以看见一个Add技巧。双击Add方式,弹出下边这个对话框:

linux环境进程间通信_linux环境进程间通信_linux环境进程间通信

图3、通过D-Bus插口估算1+2=3

在Parameters窗口输入“1,2”,点击“Execute”按钮,之后在“Output”窗口我们看见了输出结果。我们刚才创建了一个dbus服务并调用了它。

3.4.3主要流程

l通过dbus-binding-tool工具,可以将xml定义的插口文件转换成c语言的头文件。

比如:dbus-binding-tool--prefix=test_obj--mode=glib-server--output=testDbus-glue.h./testDbus.xml

l引入生成的头文件,实现插口函数。

l用dbus_g_bus_get得到sessionbus的联接

l在这个联接上用dbus_g_proxy_new_for_name函数获得到拥有指定公共名的联接的指定对象的指定插口的代理

l最后,用dbus_g_proxy_call函数通过插口代理调用插口提供的方式。

3.4.4主要插口

l通过glib的代理proxy调用方式

nFunctionforsynchronouslyinvokingamethodandreceivingreplyvalues

gbooleandbus_g_proxy_call(DBusGProxy*proxy,

constchar*method,

GError**error,

GTypefirst_arg_type,

...);

nFunctionforsynchronouslyinvokingamethodandreceivingreplyvalues.

gbooleandbus_g_proxy_call_with_timeout(DBusGProxy*proxy,

constchar*method,

inttimeout,

GError**error,

GTypefirst_arg_type,

...);

nSendsamethodcallmessageaswithdbus_g_proxy_begin_call(),butdoesnotaskforareplyorallowyoutoreceiveone.

voiddbus_g_proxy_call_no_reply(DBusGProxy*proxy,

constchar*method,

GTypefirst_arg_type,

...);

nAsynchronouslyinvokesamethodonaremoteinterface.

DBusGProxyCall*dbus_g_proxy_begin_call(DBusGProxy*proxy,

constchar*method,

DBusGProxyCallNotifynotify,

gpointeruser_data,

GDestroyNotifydestroy,

GTypefirst_arg_type,

...);

nAsynchronouslyinvokesamethodonaremoteinterface.

DBusGProxyCall*dbus_g_proxy_begin_call_with_timeout

(DBusGProxy*proxy,

constchar*method,

DBusGProxyCallNotifynotify,

gpointeruser_data,

GDestroyNotifydestroy,

inttimeout,

GTypefirst_arg_type,

linux环境进程间通信_linux环境进程间通信_linux环境进程间通信

...);

nCollectstheresultsofamethodcall.

gbooleandbus_g_proxy_end_call(DBusGProxy*proxy,

DBusGProxyCall*call,

GError**error,

GTypefirst_arg_type,

...);

nCancelsapendingmethodcall.

voiddbus_g_proxy_cancel_call(DBusGProxy*proxy,

DBusGProxyCall*call);

注:函数说明链接

3.5基于Qt的样例3.5.1对比QtDBus

注意:Qt源码编译时,须要保证系统中早已安装好dbus,之后Qt编译选项中要选支持dbus,这样会就会生成LibQtDBus.so等相关库文件。

Qt的example中有几个反例,这儿就不深究了。

3.6直接调用dbus插口

使用方法类似:

l用dbus_bus_get获取sessionbus的联接

l通过sessionbus的联接绑定等待数据

l发送数据

n异步函数调用:dbus_connection_send

n同步函数调用:dbus_connection_send_with_reply

3.7优点

低延后,低开支,高可用性:

1)低延后:DBus一开始就是拿来设计成防止来回传递和容许异步操作的。因而即使在Application和Daemon之间是通过socket实现的,并且又除去了socket的循环等待,保证了操作的实时高效。

2)低开支:DBus使用一个二补码的合同,不须要转化成像XML这样的文本格式。由于DBus是主要拿来机器内部的IPC,而不是为了网路上的IPC机制而打算的.所以它才才能在本机内部达到最优疗效。

3)高可用性:DBus是基于消息机制而不是字节流机制。它能手动管理一大堆困难的IPC问题。同样的,DBus库被设计来让程序员才能使用她们早已写好的代码。而不会让她们舍弃早已写好的代码,被迫通过学习新的IPC机制来按照新的IPC特点重画这种代码。

4AF_BUS简介

在Genivi库中以补丁的方式存在,分别对linux,glib,dbus进行了部份更改。

目前没有产生demo。

5核高基小结

按照目前现有资料剖析,基础的Linux进程间通讯方法只能逗留在字符序列上,须要进一步封装能够满足使用需求。而D-Bus则基于消息封装了底层实现,插口又有glib、qt等进行再此包装,实现上能做到低延后,低开支,高可用性,都是其使用优点。

未来使用d-bus还须要留心的几点:

l它底层是用socket封装的,是否可以轻易的在多主机间通讯,怎样配置等。

l在大数据量下,是否能够满足我们的需求。

l他自身机制和我们应用的进程线程保护之间是否有注意的地方。

6附表6.1D-Bus相关资料

一些基本概念的解释和翻译:

一个完整的DBus学习教程(强烈推荐,写得相当的全):

两个DBus的完整示例,相当有参考价值

DBus官方网站,最原滋原味的DBus学习内容

资料推荐出处:

6.2D-Bus安装

Ubuntu下安装D-Bus包:

要先装一下libdbus,执行一下以下句子就OK了

sudoapt-getinstalllibgtk2.0-dev

sudoapt-getinstalllibdbus-glib-1-dev

//另可以安装一下下边这个工具

sudoapt-getinstalld-feet

本文原创地址://lrxjmw.cn/lcydjcjtxfs.html编辑:刘遄,审核员:暂无