精华内容
下载资源
问答
  • cant build DBUS on linux

    2021-01-08 17:48:29
    ethminer/DBusInt.h:3:23: fatal error: dbus/dbus.h: No such file or directory </code></pre> <p>where is that header supposed to be?</p><p>该提问来源于开源项目:ethereum-mining/ethminer</p></div>
  • Linux - dbus基础

    2021-05-22 21:39:40
    Linux - dbus基础 文章目录Linux - dbus基础前言一、dbus是什么?二、使用步骤1.引入库2.读入数据总结 前言 提示:以下是本篇文章正文内容,下面案例可供参考 一、dbus是什么? 二、使用步骤 1.引入库 代码如下...

    Linux - dbus - 如何查看dbus有什么服务



    前言


    一、查看

    方法1:gdbus是glib的一部分,它支持bash补全。

    [thesre@centos8 ~]$ source /usr/share/bash-completion/completions/gdbus
    [thesre@centos8 ~]$ gdbus call --system --dest <TAB><TAB>  #按两次TAB键显示可能补全的选项
    com.redhat.tuned                  org.freedesktop.import1           org.freedesktop.PolicyKit1 
    fi.epitest.hostap.WPASupplicant   org.freedesktop.locale1           org.freedesktop.systemd1 
    fi.w1.wpa_supplicant1             org.freedesktop.login1            org.freedesktop.timedate1 
    org.freedesktop.DBus              org.freedesktop.machine1          
    org.freedesktop.hostname1         org.freedesktop.nm_dispatcher     
    [thesre@centos8 ~]$ gdbus call --system --dest 
    

    方法2:查看ListNames方法

    为了获得可用接口的列表,DBus导出了org.freedesktop.DBus.ListNames方法。可以通过运行以下命令来调用它:

    [thesre@centos8 ~]$ gdbus call --system --dest org.freedesktop.DBus \
    >            --object-path /org/freedesktop/DBus  \
    >            --method org.freedesktop.DBus.ListNames
    (['org.freedesktop.DBus', ':1.43204', 'org.freedesktop.login1', 'org.freedesktop.systemd1', 'com.redhat.tuned', ':1.34232', 'org.freedesktop.PolicyKit1', ':1.34233', ':1.1', ':1.2'],)
    [thesre@centos8 ~]$ 
    [thesre@centos8 ~]$ gdbus call --system --dest org.freedesktop.DBus      \
    >            --object-path /org/freedesktop/DBus       \
    >            --method org.freedesktop.DBus.ListNames | \
    >     python -c 'import sys, pprint; pprint.pprint(eval(sys.stdin.read()))'
    (['org.freedesktop.DBus',
      'org.freedesktop.login1',
      'org.freedesktop.systemd1',
      ':1.43205',
      'com.redhat.tuned',
      ':1.34232',
      'org.freedesktop.PolicyKit1',
      ':1.34233',
      ':1.1',
      ':1.2'],)
    

    dbus通信图

    在这里插入图片描述


    总结

    展开全文
  • DBUSLinux内核及用户空间的使用,与HAL及UDEV的关系。
  • Linux DBUS总线

    千次阅读 2018-03-11 20:48:23
    在Internet Tablet,也包括我们的手机系统,所有的应用程序都是使用一个用户ID运行的,所以只有一个会话通道,这一点是和Linux桌面系统是有明显区别的。  D-Bus是低延迟而且低开销的,设计得小而高效,以便...

    D-Bus三层架构

    D-Bus是一个为应用程序间通信的消息总线系统, 用于进程之间的通信。它是个3层架构的IPC 系统,包括:

    1、函数库libdbus ,用于两个应用程序互相联系和交互消息。

    2、一个基于libdbus构造的消息总线守护进程,可同时与多个应用程序相连,并能把来自一个应用程序的消息路由到0或者多个其他程序。

    3、基于特定应用程序框架的封装库或捆绑(wrapper libraries or bindings )。例如,libdbus-glib和libdbus-qt,还有绑定在其他语言,例如Python的。大多数开发者都是使用这些封装库的API,因为它们简化了D-Bus编程细节。libdbus被有意设计成为更高层次绑定的底层后端(low-levelbackend )。大部分libdbus的 API仅仅是为了用来实现绑定。

     

    总线

      在D-Bus中,“bus”是核心的概念,它是一个通道:不同的程序可以通过这个通道做些操作,比如方法调用、发送信号和监听特定的信号。在一台机器上总线守护有多个实例(instance)。这些总线之间都是相互独立的。

    一个持久的系统总线(system bus):

    它在引导时就会启动。这个总线由操作系统和后台进程使用,安全性非常好,以使得任意的应用程序不能欺骗系统事件。它是桌面会话和操作系统的通信,这里操作系统一般而言包括内核和系统守护进程。这种通道的最常用的方面就是发送系统消息,比如:插入一个新的存储设备;有新的网络连接;等等。

    还将有很多会话总线(session buses):

    这些总线当用户登录后启动,属于那个用户私有。它是用户的应用程序用来通信的一个会话总线。同一个桌面会话中两个桌面应用程序的通信,可使得桌面会话作为整体集成在一起以解决进程生命周期的相关问题。这在GNOME和KDE桌面中大量使用。

      对于一些远程的工作站,在system bus中可能会有一些问题,例如热插拔,是否需要通知远端的terminal,这会使得kernel暴露一些设备的能力,不过,我们现在关心D-Bus,是因为手持终端设备的使用,这些将不会出现。在Internet Tablet,也包括我们的手机系统,所有的应用程序都是使用一个用户ID运行的,所以只有一个会话通道,这一点是和Linux桌面系统是有明显区别的。

      D-Bus是低延迟而且低开销的,设计得小而高效,以便最小化传送的往返时间。另外,协议是二进制的,而不是文本的,这样就排除了费时的序列化过程。从开发者的角度来看,D-BUS 是易于使用的。有线协议容易理解,客户机程序库以直观的方式对其进行包装。D-Bus的主要目的是提供如下的一些更高层的功能:

    A、结构化的名字空间

    B、独立于架构的数据格式

    C、支持消息中的大部分通用数据元素

    D、带有异常处理的通用远程调用接口

    E、支持广播类型的通信

     

    Bus daemon总线守护

           Bus daemon是一个特殊的进程:这个进程可以从一个进程传递消息给另外一个进程。当然了,如果有很多applications链接到这个通道上,这个 daemon进程就会把消息转发给这些链接的所有程序。在最底层,D-Bus只支持点对点的通信,一般使用本地套接字(AF_UNIX)在应用和bus daemon之间通信。D-Bus的点对点是经过busdaemon抽象过的,由busdaemon来完成寻址和发送消息,因此每个应用不必要关心要把消息发给哪个进程。D-Bus发送消息通常包含如下步骤(正常情况下):

    创建和发送消息 给后台bus daemon进程,这个过程中会有两个上下文的切换。

    后台bus daemon进程会处理该消息,并转发给目标进程,这也会引起上下文的切换目标程序接收到消息,然后根据消息的种类,做不同的响应:要么给个确认、要么应答、还有就是忽略它。最后一种情况对于“通知”类型的消息而言,前两种都会引起进一步的上下文切换。

    综上原因,如果你准备在不同的进程之间传递大量的数据,D-Bus可能不是最有效的方法,最有效的方法是使用共享内存,但是对共享内存的管理也是相当复杂的。

     

    D-Bus进程通信简单框架

     

    D-Bus常见概念

    原生对象和对象路径

    所有使用D-BUS的应用程序都包含一些对象, 当经由一个D-BUS连接收到一条消息时,该消息是被发往一个对象而不是整个应用程序。在开发中程序框架定义着这样的对象,例如JAVA,GObject,QObject等等,在D-Bus中成为native object。

    对于底层的D-Bus协议,即libdbus API,并不理会这些native object,它们使用的是一个叫做object path的概念。通过object path,高层编程可以为对象实例进行命名,并允许远程应用引用它们。这些名字看起来像是文件系统路径,例如一个对象可能叫做“/org/kde/kspread/sheets/3/cells/4/5”。易读的路径名是受鼓励的做法,但也允许使用诸如“/com/mycompany/c5yo817y0c1y1c5b”等,只要它可以为你的应用程序所用。Namespacing的对象路径以开发者所有的域名开始(如 /org/kde)以避免系统不同代码模块互相干扰。

    简单地说:一个应用创建对象实例进行D-Bus的通信,这些对象实例都有一个名字,命名方式类似于路径,例如/com/mycompany,这个名字在全局(session或者system)是唯一的,用于消息的路由。

     

    方法和信号Methodsand Signals

    每一个对象有两类成员:方法和信号。方法就是JAVA中同样概念,方法是一段函数代码,带有输入和输出。信号是广播给所有兴趣的其他实体,信号可以带有数据payload。

    在 D-BUS 中有四种类型的消息:方法调用(method calls)、方法返回(method returns)、信号(signals)和错误(errors)。要执行 D-BUS 对象的方法,您需要向对象发送一个方法调用消息。它将完成一些处理(就是执行了对象中的Method,Method是可以带有输入参数的。)并返回,返回消息或者错误消息。信号的不同之处在于它们不返回任何内容:既没有“信号返回”消息,也没有任何类型的错误消息。

     

    接口Interface

    每一个对象支持一个或者多个接口,接口是一组方法和信号,接口定义一个对象实体的类型。D-Bus对接口的命名方式,类似org.freedesktop.Introspectable。开发人员通常将使用编程语言类的的名字作为接口名字。

     

    Proxies代理

    代理对象用来表示其他的remote object。当我们触发了proxy对象的method时,将会在D-Bus上发送一个method_call的消息,并等待答复,根据答复返回。使用非常方便,就像调用一个本地的对象。

     

    Bus Names总线名字

      当一个应用连接到bus daemon,daemon立即会分配一个名字给这个连接,称为unique connection name ,这个唯一标识的名字以冒号:开头,例如:34-907,这个名字在daemon的整个生命周期是唯一的。但是这种名字总是临时分配,无法确定的,也难以记忆,因此应用可以要求有另外一个名字well-known name 来对应这个唯一标识,就像我们使用域名来对应IP地址一样。例如可以使用com.mycompany来映射:34-907。应用程序可能会要求拥有额外的周知名字(well-knownname )。例如,你可以写一个规范来定义一个名字叫做 com.mycompany.TextEditor。你的协议可以指定自己拥有这个名字,一个应用程序应该在路径/com/mycompany /TextFileManager下有一个支持接口org.freedesktop.FileHandler的对象。应用程序就可以发送消息到这个总线名字,对象,和接口以执行方法调用。

    当一个应用结束或者崩溃是,OS kernel会关闭它的总线连接。总线发送notification消息告诉其他应用,这个应用的名字已经失去他的owner。当检测到这类notification时,应用可以知道其他应用的生命周期。这种方式也可用于只有一个实例的应用,即不开启同样的两个应用的情况。

     

    地址

    连接建立有server和client,对于bus daemon,应用就是client,daemon是server。一个D-Bus的地址是指server用于监听,client用于连接的地方,例如unix:path=/tmp/abcedf标识server将在路径/tmp/abcedf的UNIX domain socket监听。地址可以是指定的TCP/IP socket或者其他在或者将在D-Bus协议中定义的传输方式。

      如果使用bus daemon,libdbus将通过读取环境变量自动获取session bus damon的地址,通过检查一个指定的UNIX domain socket路径获取system bus的地址。如果使用D-bus,但不是daemon,需要定义那个应用是server,那个是client,并定义一套机制是他们认可server的地址,这不是通常的做法。

      通过上面的描述,我们可以获得下面的视图:

    Address –> [BusName] –> Path –> Interface –> Method

    bus name不是必要的,它只在daemon的情况下用于路由,点对点的直接连接是不需要的。

    简单地说:Address是D-Bus中server用来监听client的地址,当一个client连接上D-Bus,通常是Daemo的方式,这个client就有了一个Bus Name。其他应用可以根据消息中所带的Bus Name,来判断和哪个应用相关。消息在总线中传递的时候,传递到应用中,再根据objectpath,送至应用中具体的对象实例中,也就是是应用中根据Interface创建的对象。这些Interface有method和singal两种,用来发送、接收、响应消息。

     

    一个例子的示意图:

     

    D-Bus 消息

    消息通过D-Bus在进程间传递。有四类消息:

    一、Method call消息:将触发对象的一个method 

    二、Method return消息:触发的方法返回的结果

           三、Error消息:触发的方法返回一个异常 

    四、Signal消息:通知,可以看作为事件消息。

     

    一个消息有消息头header,里面有field,有一个消息体body,里面有参数arguments。消息头包含消息体的路由信息,消息体就是净荷payload。头字段可能包括发送者的bus名,目的地的bus名,方法或者signal名等等,其中一个头字段是用于描述body中的参数的类型,例如“i”标识32位整数,"ii”表示净荷为2个32为整数。

     

    发送Method call消息的场景

      一个method call消息从进程A到进程B,B将应答一个method return消息或者error消息。在每个call消息带有一个序列号,应答消息也包含同样的号码,使之可以对应起来。他们的处理过程如下:

    如果提供proxy,通过触发本地一个对象的方法从而触发另一个进程的远端对象的方法。应用调用proxy的一个方法,proxy构造一个method call消息发送到远端进程。

    对于底层的API,不使用proxy,应用需要自己构造method call消息。

    一个method call消息包含:远端进程的bus name,方法名字,方法的参数,远端进程中object path,可选的接口名字。

    method call消息发送到bus daemon

    bus daemon查看目的地的bus name。如果一个进程对应这个名字,bus daemon将method call消息发送到该进程中。如果没有发现匹配,bus daemon创建一个error消息作为应答返回。

    进程接收后将method call消息分拆。对于简单的底层API情况,将立即执行方法,并发送一个method reply消息给bus daemon。对于高层的API,将检查对象path,interface和method,触发一个native object的方法,并将返回值封装在一个method reply消息中。

    bus daemon收到method reply消息,将其转发到原来的进程中进程查看method reply消息,获取返回值。这个响应也可以标识一个error的残生。当使用高级的捆绑,method reply消息将转换为proxy方法的返回值或者一个exception。

    Bus daemon保证message的顺序,不会乱序。例如我们发送两个method call消息到同一个接受方,他们将按顺序接受。接收方并不要求一定按顺序回复。消息有一个序列号了匹配收发消息。

     

    发送Signal的场景

      signal是个广播的消息,不需要响应,接收方向daemon注册匹配的条件,包括发送方和信号名,bus守护只将信号发送给希望接受的进程。处理流程如下:

    一个signal消息发送到bus daemon。

    signal消息包含发布该信号的interface名字,signal的名字,进程的bus名字,以及参数。

    任何进程都可以注册的匹配条件(match rules)表明它所感兴趣的signal。总线有个注册match rules列表。

    bus daemon检查那些进程对该信号有兴趣,将信号消息发送到这些进程中。

    收到信号的进程决定如何处理。如果使用高层的捆绑,一个porxy对象将会十分一个native的信号。如果使用底层的API,进程需要检查信号的发送发和信号的名字决定如果进行处理。

     

    Introspection

      D-Bus对象可能支持一个接口org.freedesktop.DBus.Introspectable。该接口有一个方法Introspect,不带参数,将返回一个XML string。这个XML字符串描述接口,方法,信号。

    D-Bus提供两个命令dbus-monitor,可以查看bus,dbus-send命令,可以发送消息。

     

    Signal的收发小例子

    从底层,即libdbus学习如何发送signal,以及如何监听signal。signal在D-Bus的Daemon中广播,为了提高效率,只发送给向daemon注册要求该singal的对象。

     

    对于程序,第一步需要将应用和D-Bus后台建立连接,也就是和System D-Busdaemon或者Session D-Bus daemon建立连接。一旦建立,daemon会给这条连接分配一个名字,这个名字在system或者session的生命周期是唯一的,即unique connectionname,为了方便记忆,可以为这条连接分配一个便于记忆的well-known name。对于信号方式,分配这个名字不是必须的(在method_call中是需要的),因为在信号的监听中秩序给出Interface的名字和信号名称,在下面的例子中,可以将相关的代码屏蔽掉,不影响运行,但是通常我们都这样处理,尤其在复杂的程序中。在我们的例子中,定义这个BUS name为test.singal.source。当然一个好的名字,为了避免于其他应用重复,应当使用com.mycompany.myfunction之类的名字。 ,而interface的名字,一般前面和connection的BUS name一致。

     

    发送方的小程序

    [html] view plain copy
    1. #include <stdio.h>  
    2. #include <stdlib.h>  
    3. #include <string.h>  
    4. #include <dbus/dbus-glib.h>  
    5. #include <dbus/dbus.h>  
    6. #include <unistd.h>  
    7.   
    8. int send_a_signal( char * sigvalue)  
    9. {  
    10.     DBusError err;  
    11.     DBusConnection * connection;  
    12.     DBusMessage * msg;  
    13.     DBusMessageIter arg;  
    14.     dbus_uint32_t  serial =0;  
    15.     int ret;  
    16.   
    17.     //步骤1:建立与D-Bus后台的连接  
    18.       
    19.     dbus_error_init(&err);  
    20.        
    21.     connection =dbus_bus_get(DBUS_BUS_SESSION ,&err );  
    22.     if(dbus_error_is_set(&err)){  
    23.         fprintf(stderr,"ConnectionErr : %s\n",err.message);  
    24.         dbus_error_free(&err);  
    25.     }  
    26.     if(connection == NULL)  
    27.         return -1;  
    28.   
    29.     //步骤2:给连接名分配一个well-known的名字作为Bus name,这个步骤不是必须的,可以用if 0来注释着一段代码,我们可以用这个名字来检查,是否已经开启了这个应用的另外的进程。  
    30. #if 1  
    31.     ret =dbus_bus_request_name(connection,"test.singal.source",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);  
    32.     if(dbus_error_is_set(&err)){  
    33.         fprintf(stderr,"Name Err :%s\n",err.message);  
    34.         dbus_error_free(&err);  
    35.     }  
    36.     if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  
    37.         return -1;  
    38. #endif  
    39.   
    40.     //步骤3:发送一个信号  
    41.     //根据图,我们给出这个信号的路径(即可以指向对象),接口,以及信号名,创建一个Message  
    42.     if((msg =dbus_message_new_signal("/test/signal/Object","test.signal.Type","Test"))== NULL){  
    43.         fprintf(stderr,"MessageNULL\n");  
    44.         return -1;  
    45.     }  
    46.     //给这个信号(messge)具体的内容  
    47.     dbus_message_iter_init_append(msg,&arg);  
    48.    if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_STRING,&sigvalue)){  
    49.         fprintf(stderr,"Out OfMemory!\n");  
    50.         return -1;  
    51.     }  
    52.   
    53.     //步骤4: 将信号从连接中发送  
    54.     if( !dbus_connection_send(connection,msg,&serial)){  
    55.         fprintf(stderr,"Out of Memory!\n");  
    56.         return -1;  
    57.     }  
    58.     dbus_connection_flush(connection);  
    59.     printf("Signal Send\n");  
    60.   
    61.    //步骤5: 释放相关的分配的内存。  
    62.     dbus_message_unref(msg );  
    63.     return 0;  
    64. }  
    65. int main( int argc , char ** argv){  
    66.    send_a_signal("Hello,world!");  
    67.     return 0;  
    68. }  


     

    希望接收该信号的的小程序例子

    [html] view plain copy
    1. #include <stdio.h>  
    2. #include <stdlib.h>  
    3. #include <string.h>  
    4. #include <dbus/dbus-glib.h>  
    5. #include <dbus/dbus.h>  
    6. #include <unistd.h>  
    7.   
    8. void listen_signal()  
    9. {  
    10.     DBusMessage * msg;  
    11.     DBusMessageIter arg;  
    12.     DBusConnection * connection;  
    13.     DBusError err;  
    14.     int ret;  
    15.     char * sigvalue;  
    16.   
    17.      //步骤1:建立与D-Bus后台的连接  
    18.     dbus_error_init(&err);  
    19.     connection =dbus_bus_get(DBUS_BUS_SESSION, &err);  
    20.     if(dbus_error_is_set(&err)){  
    21.         fprintf(stderr,"ConnectionError %s\n",err.message);  
    22.         dbus_error_free(&err);  
    23.     }  
    24.     if(connection == NULL)  
    25.         return;  
    26.   
    27.    //步骤2:给连接名分配一个可记忆名字test.singal.dest作为Bus name,这个步骤不是必须的,但推荐这样处理  
    28.     ret =dbus_bus_request_name(connection,"test.singal.dest",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);  
    29.     if(dbus_error_is_set(&err)){  
    30.         fprintf(stderr,"Name Error%s\n",err.message);  
    31.         dbus_error_free(&err);  
    32.     }  
    33.     if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  
    34.         return;  
    35.   
    36.     //步骤3:通知D-Bus daemon,希望监听来行接口test.signal.Type的信号  
    37.     dbus_bus_add_match(connection,"type='signal',interface='test.signal.Type'",&err);  
    38.     //实际需要发送东西给daemon来通知希望监听的内容,所以需要flush  
    39.     dbus_connection_flush(connection);  
    40.     if(dbus_error_is_set(&err)){  
    41.         fprintf(stderr,"Match Error%s\n",err.message);  
    42.         dbus_error_free(&err);  
    43.     }  
    44.      
    45.     //步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是中连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。  
    46.     while(1){  
    47.         dbus_connection_read_write(connection,0);  
    48.         msg =dbus_connection_pop_message (connection);  
    49.         if(msg == NULL){  
    50.             sleep(1);  
    51.             continue;  
    52.         }  
    53.      
    54.         if(dbus_message_is_signal(msg,"test.signal.Type","Test")){  
    55.             if(!dbus_message_iter_init(msg,&arg))  
    56.                 fprintf(stderr,"MessageHas no Param");  
    57.             else if(dbus_message_iter_get_arg_type(&arg)!= DBUS_TYPE_STRING)  
    58.                 g_printerr("Param isnot string");  
    59.             else  
    60.                 dbus_message_iter_get_basic(&arg,&sigvalue);  
    61.             printf("Got Singal withvalue : %s\n",sigvalue);  
    62.         }  
    63.         dbus_message_unref(msg);  
    64.     }//End of while  
    65.          
    66. }  
    67.   
    68. int main( int argc , char ** argv){  
    69.     listen_signal();  
    70.     return 0;  
    71. }  


     

    Method的收发小例子

    监听method和监听signal的方式非常相似。在给出例子之前,我希望和上次学习一样给出一个示意图,更好地了解D-Bus的各个概念。

     

    [html] view plain copy
    1. #include <stdio.h>  
    2. #include <stdlib.h>  
    3. #include <string.h>  
    4. #include <dbus/dbus-glib.h>  
    5. #include <dbus/dbus.h>  
    6. #include <unistd.h>  
    7.   
    8.    
    9. void reply_to_method_call(DBusMessage * msg, DBusConnection * conn){  
    10.     DBusMessage * reply;  
    11.     DBusMessageIter arg;  
    12.     char * param = NULL;  
    13.     dbus_bool_t stat = TRUE;  
    14.     dbus_uint32_t level = 2010;  
    15.     dbus_uint32_t serial = 0;  
    16.      
    17.     //从msg中读取参数,这个在上一次学习中学过  
    18.    if(!dbus_message_iter_init(msg,&arg))  
    19.         printf("Message has noargs\n");  
    20.     else if(dbus_message_iter_get_arg_type(&arg)!= DBUS_TYPE_STRING)  
    21.         printf("Arg is notstring!\n");  
    22.     else  
    23.        dbus_message_iter_get_basic(&arg,& param);  
    24.     if(param == NULL) return;  
    25.   
    26.   
    27.     //创建返回消息reply  
    28.     reply = dbus_message_new_method_return(msg);  
    29.     //在返回消息中填入两个参数,和信号加入参数的方式是一样的。这次我们将加入两个参数。  
    30.     dbus_message_iter_init_append(reply,&arg);  
    31.     if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_BOOLEAN,&stat)){  
    32.         printf("Out ofMemory!\n");  
    33.         exit(1);  
    34.     }  
    35.     if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_UINT32,&level)){  
    36.         printf("Out ofMemory!\n");  
    37.         exit(1);  
    38.     }  
    39.   //发送返回消息  
    40.       if( !dbus_connection_send(conn, reply,&serial)){  
    41.         printf("Out of Memory\n");  
    42.         exit(1);  
    43.     }  
    44.     dbus_connection_flush (conn);  
    45.     dbus_message_unref (reply);  
    46. }  
    47.   
    48.    
    49. void listen_dbus()  
    50. {  
    51.     DBusMessage * msg;  
    52.     DBusMessageIter arg;  
    53.     DBusConnection * connection;  
    54.     DBusError err;  
    55.     int ret;  
    56.     char * sigvalue;  
    57.   
    58.     dbus_error_init(&err);  
    59.     //创建于session D-Bus的连接  
    60.     connection =dbus_bus_get(DBUS_BUS_SESSION, &err);  
    61.     if(dbus_error_is_set(&err)){  
    62.         fprintf(stderr,"ConnectionError %s\n",err.message);  
    63.         dbus_error_free(&err);  
    64.     }  
    65.     if(connection == NULL)  
    66.         return;  
    67.     //设置一个BUS name:test.wei.dest  
    68.     ret =dbus_bus_request_name(connection,"test.wei.dest",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);  
    69.     if(dbus_error_is_set(&err)){  
    70.         fprintf(stderr,"Name Error%s\n",err.message);  
    71.         dbus_error_free(&err);  
    72.     }  
    73.     if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  
    74.         return;  
    75.   
    76.     //要求监听某个singal:来自接口test.signal.Type的信号  
    77.    dbus_bus_add_match(connection,"type='signal',interface='test.signal.Type'",&err);  
    78.     dbus_connection_flush(connection);  
    79.     if(dbus_error_is_set(&err)){  
    80.         fprintf(stderr,"Match Error%s\n",err.message);  
    81.         dbus_error_free(&err);  
    82.     }  
    83.   
    84.     while(true){  
    85.         dbus_connection_read_write(connection,0);  
    86.         msg =dbus_connection_pop_message (connection);  
    87.   
    88.         if(msg == NULL){  
    89.             sleep(1);  
    90.             continue;  
    91.         }  
    92.   
    93.         if(dbus_message_is_signal(msg,"test.signal.Type","Test")){  
    94.             if(!dbus_message_iter_init(msg,&arg))  
    95.                fprintf(stderr,"Message Has no Param");  
    96.             elseif(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)  
    97.                 g_printerr("Param isnot string");  
    98.             else  
    99.                dbus_message_iter_get_basic(&arg,&sigvalue);  
    100.         }else if(dbus_message_is_method_call(msg,"test.method.Type","Method")){  
    101.             //我们这里面先比较了接口名字和方法名字,实际上应当现比较路径  
    102.             if(strcmp(dbus_message_get_path(msg),"/test/method/Object") == NULL)  
    103.                reply_to_method_call(msg,connection);  
    104.         }  
    105.         dbus_message_unref(msg);  
    106.     }  
    107.      
    108.      
    109. }  
    110. int main( int argc , char ** argv){  
    111.     listen_dbus();  
    112.     return 0;  
    113. }  


     

     

    [html] view plain copy
    1. #include <stdio.h>  
    2. #include <stdlib.h>  
    3. #include <string.h>  
    4. #include <dbus/dbus-glib.h>  
    5. #include <dbus/dbus.h>  
    6. #include <unistd.h>  
    7. //建立与session D-Bus daemo的连接,并设定连接的名字,相关的代码已经多次使用过了  
    8. DBusConnection * connect_dbus(){  
    9.     DBusError err;  
    10.     DBusConnection * connection;  
    11.     int ret;  
    12.   
    13.     //Step 1: connecting session bus  
    14.        
    15.     dbus_error_init(&err);  
    16.        
    17.     connection =dbus_bus_get(DBUS_BUS_SESSION, &err);  
    18.     if(dbus_error_is_set(&err)){  
    19.         fprintf(stderr,"ConnectionErr : %s\n",err.message);  
    20.         dbus_error_free(&err);  
    21.     }  
    22.     if(connection == NULL)  
    23.         return NULL;  
    24.   
    25.     //step 2: 设置BUS name,也即连接的名字。  
    26.     ret =dbus_bus_request_name(connection,"test.wei.source",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);  
    27.     if(dbus_error_is_set(&err)){  
    28.         fprintf(stderr,"Name Err :%s\n",err.message);  
    29.         dbus_error_free(&err);  
    30.     }  
    31.     if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  
    32.         return NULL;  
    33.   
    34.     return connection;     
    35. }  
    36.   
    37. void send_a_method_call(DBusConnection * connection,char * param)  
    38. {  
    39.    DBusError err;  
    40.     DBusMessage * msg;  
    41.     DBusMessageIter    arg;  
    42.     DBusPendingCall * pending;  
    43.     dbus_bool_t * stat;  
    44.     dbus_uint32_t * level;     
    45.      
    46.     dbus_error_init(&err);  
    47.   
    48.     //针对目的地地址,请参考图,创建一个method call消息。Constructs a new message to invoke a method on a remote object.  
    49.     msg =dbus_message_new_method_call ("test.wei.dest","/test/method/Object","test.method.Type","Method");  
    50.    if(msg == NULL){  
    51.         g_printerr("MessageNULL");  
    52.         return;  
    53.     }  
    54.   
    55.     //为消息添加参数。Appendarguments  
    56.     dbus_message_iter_init_append(msg, &arg);  
    57.     if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING,¶m)){  
    58.        g_printerr("Out of Memory!");  
    59.         exit(1);  
    60.     }  
    61.   
    62.     //发送消息并获得reply的handle。Queues amessage to send, as withdbus_connection_send() , but also returns aDBusPendingCall used to receive a reply to the message.  
    63.     if(!dbus_connection_send_with_reply (connection, msg,&pending, -1)){  
    64.        g_printerr("Out of Memory!");  
    65.         exit(1);  
    66.     }       
    67.   
    68.     if(pending == NULL){  
    69.         g_printerr("Pending CallNULL: connection is disconnected ");  
    70.         dbus_message_unref(msg);  
    71.         return;  
    72.     }  
    73.   
    74.     dbus_connection_flush(connection);  
    75.     dbus_message_unref(msg);  
    76.    
    77.    //waiting a reply,在发送的时候,已经获取了methodreply的handle,类型为DBusPendingCall。  
    78.     // block until we recieve a reply, Block until the pendingcall is completed.  
    79.    dbus_pending_call_block (pending);  
    80.     //get the reply message,Gets thereply, or returns NULL if none has been received yet.  
    81.     msg =dbus_pending_call_steal_reply (pending);  
    82.     if (msg == NULL) {  
    83.         fprintf(stderr, "ReplyNull\n");  
    84.          exit(1);  
    85.     }  
    86.      // free the pendingmessage handle  
    87.      dbus_pending_call_unref(pending);  
    88.     // read the parameters  
    89.     if(!dbus_message_iter_init(msg, &arg))  
    90.         fprintf(stderr, "Message hasno arguments!\n");  
    91.     else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_BOOLEAN)  
    92.         fprintf(stderr, "Argument isnot boolean!\n");  
    93.     else  
    94.         dbus_message_iter_get_basic(&arg, &stat);  
    95.    
    96.     if (!dbus_message_iter_next(&arg))  
    97.         fprintf(stderr, "Message hastoo few arguments!\n");  
    98.     else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_UINT32 )  
    99.         fprintf(stderr, "Argument isnot int!\n");  
    100.     else  
    101.         dbus_message_iter_get_basic(&arg, &level);  
    102.   
    103.     printf("Got Reply: %d,%d\n", stat, level);  
    104.     dbus_message_unref(msg);  
    105. }  
    106.   
    107. int main( int argc , char ** argv){  
    108.    DBusConnection * connection;  
    109.     connection = connect_dbus();  
    110.     if(connection == NULL)  
    111.         return -1;  
    112.   
    113.    send_a_method_call(connection,"Hello, D-Bus");  
    114.     return 0;  
    115. }  
    116.   
    展开全文
  • ubuntu12.04 安装dbus1.下载dubs下载https://dbus.freedesktop.org/releases/dbus/dbus-1.8.0.tar.gz2.配置编译./configure –prefix=/home/xx/dbus/install/ (安装目录)makemake install3.使用dbus-daemon是一个...

    ubuntu12.04 安装dbus

    1.下载dubs

    下载https://dbus.freedesktop.org/releases/dbus/

    dbus-1.8.0.tar.gz

    2.配置编译

    ./configure –prefix=/home/xx/dbus/install/ (安装目录)

    make

    make install

    3.使用

    dbus-daemon是一个后台进程,负责消息的转发

    ./dbus-daemon –config-file=../etc/dbus-1/session.conf –print-address

    会打印一个类似unix:abstract=/tmp/dbus-eW4m3qv5Pv,guid=48fba668e981b73068475c035acda368的值

    每次启动的值都不一样

    dbus-launch 是启动配置dbus-daemon的程序

    4.编译应用程序dbus.c

    gcc dbus.c -o dbus -I /home/xx/dbus/install/include/dbus-1.0/ -I /home/xx/dbus/install/lib/dbus-1.0/include/ -L /home/xx/dbus/install/lib/ -l dbus-1

    /home/xx/dbus/install/include/dbus-1.0/ 为了找到dbus/dbus.h

    /home/xx/dbus/install/lib/dbus-1.0/include/ 为了找到dbus-arch-deps.h

    -L 指定动态库的目录

    -l 要链接的动态库

    5.测试

    先运行dbus-launch打印

    ./dbus-launch

    DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-Pwy1U2h5hv,guid=9aa4b7bd692f6ffa512384615acdafb8

    DBUS_SESSION_BUS_PID=9735

    导出环境变量

    export DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-Pwy1U2h5hv,guid=9aa4b7bd692f6ffa512384615acdafb8

    运行应用程序

    ./dbus send “hello test”

    Sending signal with value hello test

    Signal Sent

    ./dbus receive

    Listening for signals

    Match rule sent

    Got Signal with value hello test

    ac830efd26f3aeec7ff6253ddf46664a.png

    6.Dbus 调试工具 D-feet

    安装 apt-get install d-feet

    使用:填写Bus Address

    4a082d5bbc0d92a8e26a98c1ddebf125.png

    7.dbus-send的使用

    dbus-send :发送信息到message bus

    dbus-send [--system | --session] [--dest=NAME] [--print-reply] [--type=TYPE]

    path> [contents ...]

    --system :指系统总线(System Bus),用于系统Linux和用户程序间进行通信

    --session:指会话总线(Session Bus),用于桌面用户程序之间的通信

    如果不指定选项,默认使用--session

    --dest :是必须的选项,是准备发往bus上的名字描述

    --dest= 连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值

    支持的参数类型包括:string, int32, uint32, double, byte, boolean。

    --print-reply:打印接收到的返回信息

    --type=TYPE:指定"method_call"或者"signal"(默认是signal)

    eg:

    dbus-send --system --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListActivatableNames

    连接名:org.freedesktop.DBus

    对象路径:/

    接口名.方法名org.freedesktop.DBus.ListActivatableNames

    返回:

    method return sender=org.freedesktop.DBus -> dest=:1.217 reply_serial=2

    array [

    string "org.freedesktop.DBus"

    string "com.ubuntu.LanguageSelector"

    string "org.freedesktop.ColorManager"

    string "com.hp.hplip"

    string "com.ubuntu.USBCreator"

    string "com.ubuntu.SoftwareProperties"

    string "org.freedesktop.Avahi"

    string "org.freedesktop.PolicyKit1"

    string "org.debian.apt"

    string "org.freedesktop.hostname1"

    string "org.gnome.CPUFreqSelector"

    string "org.freedesktop.ConsoleKit"

    string "com.ubuntu.DeviceDriver"

    string "org.freedesktop.UPower"

    string "org.freedesktop.PackageKit"

    string "org.freedesktop.UDisks"

    string "org.freedesktop.ModemManager"

    string "com.ubuntu.SystemService"

    string "fi.epitest.hostap.WPASupplicant"

    string "org.debian.AptXapianIndex"

    string "org.freedesktop.RealtimeKit1"

    string "fi.w1.wpa_supplicant1"

    string "org.freedesktop.Accounts"

    string "com.ubuntu.WhoopsiePreferences"

    string "org.freedesktop.locale1"

    string "org.gnome.SettingsDaemon.DateTimeMechanism"

    string "org.freedesktop.nm_dispatcher"

    string "org.opensuse.CupsPkHelper.Mechanism"

    ]

    8.dbus-monitor使用

    填写interface接口名监听

    $ dbus-monitor --session "interface='com.example.dbus.Interface'"

    signal sender=org.freedesktop.DBus -> dest=:1.1716 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired

    string ":1.1716"

    method call sender=:1.1717 -> dest=com.example.dbus serial=2 path=/; interface=com.example.dbus.Interface; member=add

    int32 5

    int32 8

    展开全文
  • Linux DBUS客户端程序

    2019-12-19 10:40:18
    DBUS客户端程序,发送一个信号,信号携带int型数据。信号的object path为"/test/signal/server",interface名为 "test.signal.Type",信号名为"Test"。接收端可以根据这三个属性来判断是否是想接收的信号。 使用...

    DBUS客户端程序,发送一个信号,信号携带int型数据。信号的object path为"/test/signal/server",interface名为 "test.signal.Type",信号名为"Test"。接收端可以根据这三个属性来判断是否是想接收的信号。

        使用dbus前要建立一个连接,通过这个连接连到dbus总线。DBusConnection *dbus_bus_get (DBusBusType type, DBusError *error) 函数就是建立连接用的。第一个参数为dbus连接类型,分为DBUS_BUS_SESSION(会话总线)和DBUS_BUS_SYSTEM(系统总线)。第二个参数用来返回错误消息。返回结果是与dbus建立的连接。

        连接建立好了,为了方便使用需要给它起个名字,用dbus_bus_request_name()函数。

        dbus_message_new_signal()用来创建一个信号。有个信号还需要往里添加数据。我把DBusMessageIter相当于一个数据容器指针。然后使用dbus_message_iter_init_append()将信号和数据指针挂上关系。然后往DBusMessageIter里挂数据,间接的往信号里放数据。再使用dbus_connection_send()把数据发出去,剩下的就等着接收端收了。

    dbus_connection_send()表示发送消息,并且不接收返回。如果发送的消息需要回应,可使用dbus_connection_send_with_reply()函数。用法如下:

    DBusPendingCall *pending_return;
    if (!dbus_connection_send_with_reply(conn, msg, &pending_return, -1))	//发送后需要对方返回
    {
            cout<<"Error in dbus_connection_send_with_reply\n";
            exit(1);
    }
    
    if(pending_return == NULL)
    {
            cout<<"pending return is NULL"<<endl;
            exit(1);
    }
    dbus_connection_flush(conn);	//阻塞程序,直到传出消息队列为空
    dbus_message_unref(msg);	//减少DBusMessage的引用计数,如果计数为0,则释放消息
    dbus_pending_call_block(pending_return); //阻塞,直到pending call完成
    
    DBusMessage *reply;
    if ((reply = dbus_pending_call_steal_reply(pending_return)) == NULL)	//获得返回消息
    {
            cout<<"Error in dbus_pending_call_steal_reply"<<endl;
            exit(1);
    }
    
    dbus_pending_call_unref(pending_return);	//减少pending call的参考计数,如果计数达到0,则将其释放
    char *s;
    if (dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) 
    //得到消息内容。DBUS_TYPE_STRING表示消息类型,DBUS_TYPE_INVALID终止列表。此处表示判断是否获得DBUS_TYPE_STRING类型的消息
    {
            cout<<"get reply: "<<s<<endl;
    }
    
    dbus_message_unref(reply);

     发送程序示意图:

    //dbusclient.cpp
    #include <iostream>
    #include <stdlib.h>
    #include <dbus/dbus.h>
    #include <unistd.h>
    #include <strings.h>
    
    using namespace std;
    
    const int RES_SUCCESS = -1;
    const int RES_FAILED = 0;
    
    int my_dbus_initialization(char const *_bus_name, DBusConnection **_conn, DBusBusType bustype)
    {
        DBusError err;
        int ret;
        dbus_error_init(&err);					//DBusError need init before use
        *_conn = dbus_bus_get(bustype, &err);
        if (dbus_error_is_set(&err))
        {
            cout<<"Connection error"<<endl;
            dbus_error_free(&err);
            return RES_FAILED;
        }
    
        ret = dbus_bus_request_name(*_conn, _bus_name, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
        if (dbus_error_is_set(&err))
        {
            cout<<"Request name error"<<endl;
            dbus_error_free(&err);
            return RES_FAILED;
        }
    
        if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret)
        {
            cout<<"owner failed"<<endl;
            return RES_FAILED;
        }
    
        return RES_SUCCESS;
    }
    
    int my_dbus_send_signal(DBusConnection *conn, uint32_t number)
    {
        dbus_uint32_t serial = 0;
        DBusMessage *msg;
        DBusMessageIter args;
    
        msg = dbus_message_new_signal("/test/signal/server",        //object name of the signal
                                      "test.signal.Type",           //interface name of the signal
                                      "Test");                      //name of signal
    
        if (NULL == msg)
        {
            cout<<"Message Null";
            return RES_FAILED;
        }
    
        dbus_message_iter_init_append(msg, &args);
    
        if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &number))
        {
            cout<<"Out of memory"<<endl;
            return RES_FAILED;
        }
    	cout<<"send data: "<<number<<endl;
        if (!dbus_connection_send(conn, msg, &serial))
        {
            cout<<"out of memory"<<endl;
            dbus_message_unref(msg);
            return RES_FAILED;
        }
        dbus_connection_flush(conn);
        dbus_message_unref(msg);
    
        return RES_SUCCESS;
    }
    
    
    int main(int argc, char** argv)
    {
        DBusConnection *conn;
     
        if (RES_FAILED == my_dbus_initialization("test.signal.client", &conn, DBUS_BUS_SESSION))
        {
            exit(1);
        }
        cout<<"please input a number:";
        uint32_t number;
        cin>>number;
        my_dbus_send_signal(conn, number);
    
    
        return 0;
    }
    

    //编译命令:g++ -o dbusclient dbusclient.cpp -ldbus-1

     

    展开全文
  • linux搭建Dbus教程

    2020-09-06 21:42:39
    2.下面开始搭建Dbus平台:在 /home/csap 路径下搭建Dbus平台 (输入pwd查看当前目录路径) 搭建Dbus需要的组件有 注意:还需要额外安装nginx 基础组建: zookeeper 3.4.6 (集群都装) kafka 0.10.0.0 ...
  • LINUX下的DBUS

    2020-04-14 11:28:31
    文章目录D-BUS通信特点技术实现实现原理连接到总线信号发送与接收信号发送信号接收函数调用和提供函数调用函数调用提供函数调用实例建立连接断开连接发送信号(Sending Signal)调用方法...DBUS是一种高级的进程...
  • Linux DBUS服务器端程序

    2019-12-19 18:03:06
    DBus 服务器端接收方式 DBus 服务器端用来接收signal和method调用。从收集的资料中发现,主要有三种接收方式。 一,采用while循环,监听dbus_connection_read_write()函数。有消息到来时在循环内部进行处理。优点...
  • <p>If there is some technique which would make my life with Dbus more efficient and reliable, please let Me know, Sure, I Am ready to test with you and reinstall whole distro, if something will crash....
  • linux DBUS 实例讲解

    热门讨论 2011-08-18 14:31:46
    注:该文档不是我原创的,摘自http://blog.csdn.net/fmddlmyy,我只是把相关文档整合在一起,希望有需要的朋友看起来能够方便一些。
  • server/websocket_keylogger_dbus.py' which implements and WebSocket keylogger using DBus. <p>This is just an initial implementation to check that you are happy to include such code in your project....
  • <div><ul><li>This is only for Linux and with it Spyder and IPython qtconsole work correctly under KDE.</li><li>The lack of <code>libQtDBus</code> in Anaconda makes Oxygen (the default KDE theme) ...
  • [linux] dbus sharing design

    2020-11-21 20:26:40
    Each service creates its own thread to drive DBUS: Thread, BLE, WiFi. Need a consistent way to register such services to drive DBUS in a common way. <p>#### Proposed Solution <p>Map out pros and cons...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,644
精华内容 1,057
关键字:

dbuslinux

linux 订阅