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
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方式,弹出下边这个对话框:
图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,
...);
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
本文原创地址://gulass.cn/lcydjcjtxfs.html编辑:刘遄,审核员:暂无