对libdbus库函数使用的理解

1.D-BUS 的内部工作方式

典型的D-BUS设置将由几个总线构成。将有一个持久的系统总线(system bus),它在引导时就会启动。这个总线由操作系统和后台进程使用,安全性非常好,以使得任意的应用程序不能欺骗系统事件。还将有很多会话总线(session buses),这些总线当用户登录后启动,属于那个用户私有。它是用户的应用程序用来通信的一个会话总线。如果一个应用程序需要接收来自系统总线的消息,可以直接连接到系统总线 —— 不过,它可以发送的消息将是受限的。只有Linux内核、Linux桌面环境和权限较高的程序才能向系统总线写入消息,以此保障系统安全性,防止有恶意进程假冒Linux发送消息。

一旦应用程序连接到了一个总线,它们就必须通过添加匹配器(matchers)来声明它们希望收到哪种消息。匹配器为可以基于接口、对象路径和方法进行接收的消息指定一组规则。这样就使得应用程序可以集中精力去处理它们想处理的内容,以实现消息的高效路由,并保持总线上消息的预期数量,以使得不会因为这些消息导致所有应用程序的性能下降并变得很慢。

1.1对象

本质上,D-BUS是一个对等(peer-to-peer)的协议 —— 每个消息都有一个源和一个目的。这些地址被指定为对象路径。概念上,所有使用 D-BUS 的应用程序都包括一组对象,消息发送到或者发送自某一个对象,这些对象由对象路径来唯一标识。

每个对象都可以支持一个或多个接口(interfaces)。这些接口看起来类似于 Java 中 的接口或者 C++ 中的纯粹的虚类(pure virtual classes)。一个接口就是多个方法和信号的集合。dbus使用简单的命名空间字符串来表示接口,如org.freedesktop.Introspectable。

1.2消息

在 D-BUS 中有四种类型的消息:

1.方法调用(method call) 在对象上执行一个方法

2.方法返回(method reply)返回方法执行的结果

3.错误(error)调用方法产生的异常

4.信号(signal)通知指定的信号发生了,可以想象成“事件”。

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

消息也可以有任意的参数。参数是强类型的,类型的范围是从基本的非派生类型(布尔(booleans)、 字节(bytes)、整型(integers))到高层次数据结构(字符串(strings)、数组( arrays)和字典(dictionaries))。

2.D-Bus low-level API的使用

2.1建立服务的流程

建立一个dbus连接之后 -- dbus_bus_get(),为这个连接注册监视函数--dbus_connection_set_watch_functions(),为这个连接注册超时函数--dbus_connection_set_timeout_functions(),为这个连接注册消息处理函数--dbus_connection_add_filter(),为这个dbus连接(DbusConnection)起名 -- dbus_bus_request_name(),这个名字将会成为我们在后续进行远程调用的时候的服务名,为这个连接添加匹配器dbus_bus_add_match(),将对象路径注册到总线,然后我们进入文件描述符读写就绪状态监听循环。在循环中,我们从总线上取出消息 -- dbus_watch_handle(),然后通过dbus_connection_dispatch()分发给前面通过dbus_connection_add_filter()注册的消息处理函数,并通过比对消息中的方法接口名和方法名 -- dbus_message_is_method_call(),如果一致,那么我们跳转到相应的处理中去。在相应的处理中,我们会从消息中取出远程调用的参数。并且建立起回传结果的通路 -- reply_to_method_call()。回传动作本身等同于一次不需要等待结果的远程调用。

2.2发送信号的流程:

建立一个dbus连接之后,为这个dbus连接起名,建立一个发送信号的通道,注意,在建立通道的函数中,需要我们填写该信号的接口名和信号名 -- dbus_message_new_signal()。然后我们把信号对应的相关参数压进去 -- dbus_message_iter_init_append(); dbus_message_iter_append_basic()。然后就可以启动发送了 -- dbus_connection_send(); dbus_connection_flush。

2.3 进行一次远程调用的流程:

建立好dbus连接之后,为这dbus连接命名,申请一个远程调用通道 -- dbus_message_new_method_call(),注意,在申请远程调用通道的时候,需要填写服务器名,本次调用的接口名,和本次调用名(方法名)。压入本次调用的参数 -- dbus_message_iter_init_append(); dbus_message_iter_append_basic(),实际上是申请了一个首地址,我们就是把我们真正要传的参数,往这个首地址里面送(送完之后一般都会判断是否内存越界了)。然后就是启动发送调用并释放发送相关的消息结构 -- dbus_connection_send_with_reply()。这个启动函数中带有一个句柄。我们马上会阻塞等待这个句柄给我们带回总线上回传的消息。当这个句柄回传消息之后,我们从消息结构中分离出参数。用dbus提供的函数提取参数的类型和参数 -- dbus_message_iter_init(); dbus_message_iter_next(); dbus_message_iter_get_arg_type(); dbus_message_iter_get_basic()。也就达成了我们进行本次远程调用的目的了。

2.4信号接收流程:

建立一个dbus连接之后,为这个dbus连接起名,为我们将要进行的消息循环添加匹配条件(就是通过信号名和信号接口名来进行匹配控制的) -- dbus_bus_add_match()。我们进入等待循环后,只需要对信号名,信号接口名进行判断就可以分别处理各种信号了。在各个处理分支上。我们可以分离出消息中的参数。对参数类型进行判断和其他的处理。

3.D-Bus low-level public API的使用理解

3.1关于DBusConnection的理解

DBusConnection代表着和总线或者另外一个应用的连接,通过它可以来来发送和接收消息,通过函数dbus_bus_get()函数,来连接到一个已经公布名称的总线,进而获取一个DBusConnection连接。DBusConnection可以看做是一个维护着接收和发送的两个消息队列,它基于SOCKET进行数据的传送。

DBusConnection上通过DBusWatchDBusTimeout两个对象来决定何时进行消息接收、消息发送和消息分发的处理操作,通过dbus_connection_dispatch()函数,来处理接收消息队列最顶端的一个消息,dbus_connection_dispatch()函数内部会执行已经注册过的消息处理函数(在resourcemanager程序中是msg_filter()函数)。删除接收消息队列中这个处理过的消息,然后返回。

dbus_connection_get_dispatch_status()函数指示是否队列中需要等待处理的消息。

为了达到对消息队列的异步处理,我们需要两个函数dbus_connection_set_watch_functions(), dbus_connection_set_timeout_functions() 来整合DBusConnection到我们函数自己的主循环中去(在resourcemanger程序中是bus_watch_daemon)。如果不需要异步处理的话,可以忽略对象DBusWatch, DBusTimeout以及函数dbus_connection_dispatch().然后就需要使用函数 dbus_connection_read_write_dispatch().

当使用函数dbus_connection_send()发送消息的时候,消息被添加到DBusConnection的发送队列中去,如果执行dbus_connection_flush()函数,那么进程将被阻塞,直到发送队列中的消息被通过SOCKET完全传送出去;如果不执行该函数,则会在下次主循环执行dbus_watch_handle的时候被通过SOCKET传送出去。

当连接被断开的时候,会在 interface DBUS_INTERFACE_LOCAL, path DBUS_PATH_LOCAL上接收到“Disconnected”信号,在连接被断开以前,必须保持对DBusConnection的引用。

3.2 关于DBusMessage的理解

消息DBusMessage通过DBusConnection进行发送和接收。

消息具有消息头,消息头的属性通过函数dbus_message_get_type()来获取,消息包含的消息头,指示了消息的来源 消息的目标地 方法调用或信号调用 以及其他信息,通过函数dbus_message_get_member()来获取。也可以通过更加简便的方式来获取,包括

dbus_message_is_method_call(),判断是否是方法调用

dbus_message_is_signal(),判断是否是信号消息

dbus_message_is_error()判断是否是出错消息

消息携带的参数,通过dbus_message_get_signature()来获取签名,对于简单的参数通过dbus_message_get_args()来获取,对于复杂的结构体参数,通过DBusMessageIter来获得。

时间: 2024-10-06 08:27:55

对libdbus库函数使用的理解的相关文章

4.RCC外设的学习和理解

RCC时钟模块并不好理解,初次接触我也是一头雾水,而且我真正掌握它的时候也比较晚,是我在学习用寄存器控制开发板时才真正了解他的运行原理和规律,但我为什么重新修订后却放在了前列,因为这是整个嵌入式的基础之一,初学者是比较难,但是我还是希望最好能够掌握,因为实时性对于嵌入式系统很重要,而基础正是要了解从系统时钟到你选定的每一个模块它的时钟频率,理解这个模块对于学习以后所有模块都很有用,闲话不多说,进入正题: 初看此图是不是感觉太复杂了,事实上我第一次看这张图的时候也是的,完全理不清结构,但是下面我带

1.4 算法分析

练习 1.4.1 证明从N个数中取三个整数的不同组合为 N(N-1)(N-2)/6.     /*下面的证明也恰好符合帕斯卡恒等式(1.1.27)*/ 方法一:直接根据排列组合的知识---C(N,3)=N(N-1)(N-2)/6 方法二:数学归纳法如下 1.4.2 修改TreeSum,正确处理两个较大的int值相加可能溢出的情况          /*对一些"极端"情况进行考虑*/ public class ThreeSum { public static int count(int[

有意思的字符串查找函数

通过一段时间对字符串的了解,我发现了许多有意思的字符串函数,下面我们就以常见的字符串查找函数:strchr,strrchr,strstr,strrstr为例来模拟实现这些有意思的字符串查找函数. [strchr][strrchr] 查找一个字符,有所不同的是:strchr用于查找这个字符第一次出现的位置,strrchr用于查找这个字符最后一次出现的位置.下面我们就来打开MSDN来查找这两个字符查找函数的函数原型: char *strchr(const char *string,int c) ch

关于系统调用、库函数的理解

这里不是去说系统调用.函数和程序的含义,这些网上有太多定义,但是如何结合现实生活中的事物去更好的理解它们呢?这就是我要说的. 什么是系统调用:就好像是组成汉字的笔画,无论是哪个汉字,所能用到的笔画就那几个,它是组成汉字的最小单位. 什么是库函数:就是笔画不同组合形成的众多汉字,它是文章组成的最小单位. 什么是程序:就是用不同汉字写成的不同形式的文章,诗词歌赋等等. 系统调用是对内核功能的调用,而系统调用也是内核最小的功能实现单位,但是如果让程序员开发程序去直接使用系统调用是否可以呢?答案是肯定的

深入理解计算机系统9个重点笔记

引言 深入理解计算机系统,对我来说是部大块头.说实话,我没有从头到尾完完整整的全部看完,而是选择性的看了一些我自认为重要的或感兴趣的章节,也从中获益良多,看清楚了计算机系统的一些本质东西或原理性的内容,这对每个想要深入学习编程的程序员来说都是至关重要的.只有很好的理解了系统到底是如何运行我们代码的,我们才能针对系统的特点写出高质量.高效率的代码来.这本书我以后还需要多研究几遍,今天就先总结下书中我已学到的几点知识. 重点笔记 编写高效的程序需要下面几类活动: 选择一组合适的算法和数据结构.这是很

从头到尾彻底理解KMP

从头到尾彻底理解KMP 本文转自:http://blog.csdn.net/v_july_v/article/details/7041827 作者:July时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个多月不断反复改进.后收录于新书<编程之法:面试和算法心得>第4.4节中. 1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP,思路混乱导致写也写得混乱.所以一直想找机会重新写下KMP,但苦于一直以来对KMP的理解始终不够

Python 多进程实战 & 回调函数理解与实战

这篇博文主要讲下笔者在工作中Python多进程的实战运用和回调函数的理解和运用. 多进程实战 实战一.批量文件下载 从一个文件中按行读取 url ,根据 url 下载文件到指定位置,用多进程实现. #!/usr/local/python27/bin/python2.7 from multiprocessing import Process,Pool import os,time,random,sys import urllib # 文件下载函数 def filedown(url,file):  

Linux系统的理解及学习Linux内核的心得

作业列表      linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作 linux内核分析作业:操作系统是如何工作的进行:完成一个简单的时间片轮转多道程序内核代码 linux内核分析作业3:跟踪分析Linux内核的启动过程 linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 linux内核分析作业5:分析system_call中断处理过程 linux内核分析作业6:分析Linux内核创建一个新进程的过程 Linux内核分析作业7:L

STM32启动过程的理解

对于STM32启动的过程,想象中应该是这样的上电--->启动---->main() 由于现在的集成开发环境,对于C语言之下的东西似乎都被屏蔽了,另外用编程也大都用封装好的库函数,连对寄存器的了解都少了一大步,但是这样总是让人觉得根基不够稳重.今天就整理下启动代码的理解,补充一下. 1.STM32存储器的组织 STM32作为32bit的操作系统,自然是2^32的寻址范围,所以正好是4GB的空间,再看一下对这个4GB是怎么分配的 8*512MB=4GB,图上很清晰了,一共分为  Code区  SR