精华内容
下载资源
问答
  • dbus_00】dbus在ubuntu18.04上的安装

    千次阅读 2019-04-24 00:28:49
    sudo apt-get install dbus ...安装d-feet,用于查看 session bus 和 system bus sudo apt-get install d-feet 安装glib2.0, 这步安装的会比较多 sudo apt-get install libgtk2.0-dev 安装 dbus-glib apt-get ins...
    1. sudo apt-get install dbus
      18.04我这边默认是已安装的,如下图所示:
      在这里插入图片描述
    2. 安装d-feet,用于查看 session bus 和 system bus
      sudo apt-get install d-feet
      在这里插入图片描述
    3. 安装glib2.0, 这步安装的会比较多
      sudo apt-get install libgtk2.0-dev
      在这里插入图片描述
    4. 安装 dbus-glib
      apt-get install libdbus-glib-1-dev
      在这里插入图片描述
    5. 整理dbus路径

    5.1 进入/usr/include下,将/usr/include/dbus-1.0/dbus文件夹复制到/usr/include下
    5.2.将/usr/lib/x86_64-linux-gnu/dbus下dbus-arch-deps.h文件复制到
    /usr/include/dbus下
    5.3.将/usr/include/glib-2.0下所有文件及文件夹复制至/usr/include/下
    5.4.将/usr/lib/x86_64-linux-gnu/glib-2.0/include下glibconfig.h复制到/usr/include/下

    这里也整理好了dbus_Include路径,可以将里面的所有文件到拷贝至/usr/include下即可,文件链接-》
    在这里插入图片描述

    1. 使用dbus服务端和客户端代码进行测试,看看dbus环境是否正常
    // 服务端代码
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dbus/dbus.h>
    #include <unistd.h>
    
    void listen_signal()
    {
        DBusMessage * msg;
        DBusMessageIter arg;
        DBusConnection * connection;
        DBusError err;
        int ret;
        char * sigvalue;
    
         //步骤1:建立与D-Bus后台的连接
        dbus_error_init(&err);
        connection =dbus_bus_get(DBUS_BUS_SESSION, &err);
        if(dbus_error_is_set(&err)){
            fprintf(stderr,"ConnectionError %s\n",err.message);
            dbus_error_free(&err);
        }
        if(connection == NULL)
            return;
    
       //步骤2:给连接名分配一个可记忆名字test.singal.dest作为Bus name,这个步骤不是必须的,但推荐这样处理
        ret =dbus_bus_request_name(connection,"test.singal.dest",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);
        if(dbus_error_is_set(&err)){
            fprintf(stderr,"Name Error%s\n",err.message);
            dbus_error_free(&err);
        }
        if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
            return;
    
        //步骤3:通知D-Bus daemon,希望监听来行接口test.signal.Type的信号
        dbus_bus_add_match(connection,"type='signal',interface='test.signal.Type'",&err);
        //实际需要发送东西给daemon来通知希望监听的内容,所以需要flush
        dbus_connection_flush(connection);
        if(dbus_error_is_set(&err)){
            fprintf(stderr,"Match Error%s\n",err.message);
            dbus_error_free(&err);
        }
    
        //步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是中连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
        while(1){
            dbus_connection_read_write(connection,0);
            msg =dbus_connection_pop_message (connection);
            if(msg == NULL){
                sleep(1);
                continue;
            }
    
            if(dbus_message_is_signal(msg,"test.signal.Type","Test")){
                if(!dbus_message_iter_init(msg,&arg))
                    fprintf(stderr,"MessageHas no Param");
                else if(dbus_message_iter_get_arg_type(&arg)!= DBUS_TYPE_STRING)
                    fprintf(stderr,"Param isnot string");
                else
                    dbus_message_iter_get_basic(&arg,&sigvalue);
                printf("Recetive Singal Value : %s\n",sigvalue);
            }
            dbus_message_unref(msg);
        }//End of while
    
    }
    int main(void){
    
        printf("------Start Listen_signal!-------\n");
        listen_signal();
        return 0;
    }
    
    // 客户端代码
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dbus/dbus-glib.h>
    #include <dbus/dbus.h>
    #include <unistd.h>
    
    int send_a_signal( char * sigvalue)
    {
        DBusError err;
        DBusConnection * connection;
        DBusMessage * msg;
        DBusMessageIter arg;
        dbus_uint32_t  serial =0;
        int ret;
    
        dbus_error_init(&err);
    
        //步骤1:建立与D-Bus后台的连接
        //
        connection =dbus_bus_get(DBUS_BUS_SESSION ,&err );
        if(dbus_error_is_set(&err)){
            fprintf(stderr,"ConnectionErr : %s\n",err.message);
            dbus_error_free(&err);
        }
        if(connection == NULL)
            return -1;
    
        //步骤2:给连接名分配一个well-known的名字作为Bus name,这个步骤不是必须的,可以用if 0来注释着一段代码,我们可以用这个名字来检查,是否已经开启了这个应用的另外的进程。
    #if 1
        ret =dbus_bus_request_name(connection,"test.singal.source",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);
        if(dbus_error_is_set(&err)){
            fprintf(stderr,"Name Err :%s\n",err.message);
            dbus_error_free(&err);
        }
        if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
            return -1;
    #endif
    
        //步骤3:发送一个信号
        //根据图,我们给出这个信号的路径(即可以指向对象),接口,以及信号名,创建一个Message
        if((msg =dbus_message_new_signal("/test/signal/Object","test.signal.Type","Test"))== NULL){
            fprintf(stderr,"MessageNULL\n");
            return -1;
        }
        //给这个信号(messge)具体的内容
        dbus_message_iter_init_append(msg,&arg);
       if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_STRING,&sigvalue)){
            fprintf(stderr,"Out OfMemory!\n");
            return -1;
        }
    
        printf("Signal Send: %s\n",sigvalue);
        //步骤4: 将信号从连接中发送
        if( !dbus_connection_send(connection,msg,&serial)){
            fprintf(stderr,"Out of Memory!\n");
            return -1;
        }
        dbus_connection_flush(connection);
        printf("--------Success Signal Send----------\n");
    
       //步骤5: 释放相关的分配的内存。
        dbus_message_unref(msg );
        return 0;
    }
    
    int main(void)
    {
        printf("------Start Send_a_signal!-------\n");
        send_a_signal("hello ");
        return 0;
    }
    

    效果如下图所示,即说明通讯成功,dbus环境正常:
    在这里插入图片描述

    展开全文
  • dbus

    2019-12-10 19:13:16
    dbus填坑记录 如果普通用户登陆,不能用root用户创建DBUS_BUS_... DBUS_BUS_SYSTEM类型需要在/etc/dbus-1/system.d/中增加定义,比如 <busconfig> <policy user="root"> <allow own="uk.org.th...

    dbus填坑记录

    1. 如果普通用户登陆,不能用root用户创建DBUS_BUS_SESSION类型的dbus
    2. DBUS_BUS_SYSTEM类型需要在/etc/dbus-1/system.d/中增加定义,比如
      <busconfig>
              <policy user="root">
                      <allow own="uk.org.thekelleys.dnsmasq"/>
                      <allow send_destination="uk.org.thekelleys.dnsmasq"/>
              </policy>
              <policy context="default">
                      <deny own="uk.org.thekelleys.dnsmasq"/>
                      <deny send_destination="uk.org.thekelleys.dnsmasq"/>
              </policy>
      </busconfig>

       

    3. 普通用户sudo执行时,DBUS_BUS_SESSION类型和DBUS_BUS_SYSTEM不能通信。

    DBUS_BUS_SESSION

    这种类型的dbus不能用root用户创建,否则会报如下错误

    dbus_bus_get failed: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11

    如果加上    setenv("DISPLAY", ":0", true);又会报如下错误

    dbus_bus_get failed: /usr/bin/dbus-launch terminated abnormally with the following error: No protocol specified
    Autolaunch error: X11 initialization failed.

    DBUS_BUS_SYSTEM

    直接用会报如下错误

    dbus_bus_request_name failed: Connection ":1.21" is not allowed to own the service "xxx" due to security policies in the configuration file
    dbus[19129]: Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.
      D-Bus not built with -rdynamic so unable to print a backtrace
    Aborted

    必须在/etc/dbus-1/system.d/中增加相应的定义

    dbus_bus_add_match

    网上查到的粟子中,基本上都是type='signal',interface='%s',其实match的规则可以有很多,比如type, interface,sender,destination,所有的规则可以单独出现,也可以组合,实际使用中根据需要选择。

    展开全文
  • D_bus进程间通信

    2013-07-09 17:15:44
    DBUS基础知识 1. 进程间使用D-Bus通信  D-Bus是一种高级的进程间通信机制,它由freedesktop.org项目提供,使用GPL许可证发行。D-Bus最主要的用途是在Linux桌面环境为进程提供通信,同时能将Linux桌面环境和...
    DBUS基础知识

    1.  进程间使用D-Bus通信
        D-Bus是一种高级的进程间通信机制,它由freedesktop.org项目提供,使用GPL许可证发行。D-Bus最主要的用途是在Linux桌面环境为进程提供通信,同时能将Linux桌面环境和Linux内核事件作为消息传递到进程。D-Bus的主要概率为总线,注册后的进程可通过总线接收或传递消息,进程也可注册后等待内核事件响应,例如等待网络状态的转变或者计算机发出关机指令。目前,D-Bus已被大多数Linux发行版所采用,开发者可使用D-Bus实现各种复杂的进程间通信任务。
        
    2.  D-Bus的基本概念
        D-Bus是一个消息总线系统,其功能已涵盖进程间通信的所有需求,并具备一些特殊的用途。D-Bus是三层架构的进程间通信系统,其中包括:
        接口层:接口层由函数库libdbus提供,进程可通过该库使用D-Bus的能力。
        总线层:总线层实际上是由D-Bus总线守护进程提供的。它在Linux系统启动时运行,负责进程间的消息路由和传递,其中包括Linux内核和Linux桌面环境的消息传递。
        包装层:包装层一系列基于特定应用程序框架的Wrapper库。
        
        D-Bus具备自身的协议,协议基于二进制数据设计,与数据结构和编码方式无关。该协议无需对数据进行序列化,保证了信息传递的高效性。无论是libdbus,还是D-Bus总线守护进程,均不需要太大的系统开销。
        
        总线是D-Bus的进程间通信机制,一个系统中通常存在多条总线,这些总线由D-Bus总线守护进程管理。最重要的总线为系统总线(System Bus),Linux内核引导时,该总线就已被装入内存。只有Linux内核、Linux桌面环境和权限较高的程序才能向该总线写入消息,以此保障系统安全性,防止有恶意进程假冒Linux发送消息。
        
        会话总线(Session Buses)由普通进程创建,可同时存在多条。会话总线属于某个进程私有,它用于进程间传递消息。
        进程必须注册后才能收到总线中的消息,并且可同时连接到多条总线中。D-Bus提供了匹配器(Matchers)使进程可以有选择性的接收消息,另外运行进程注册回调函数,在收到指定消息时进行处理。匹配器的功能等同与路由,用于避免处理无关消息造成进程的性能下降。除此以外,D-Bus机制的重要概念有以下几个。
        对象:对象是封装后的匹配器与回调函数,它以对等(peer-to-peer)协议使每个消息都有一个源地址和一个目的地址。这些地址又称为对象路径,或者称之为总线名称。对象的接口是回调函数,它以类似C++的虚拟函数实现。当一个进程注册到某个总线时,都要创建相应的消息对象。
        消息:D-Bus的消息分为信号(signals)、方法调用(method calls)、方法返回(method returns)和错误(errors)。信号是最基本的消息,注册的进程可简单地发送信号到总线上,其他进程通过总线读取消息。方法调用是通过总线传递参数,执行另一个进程接口函数的机制,用于某个进程控制另一个进程。方法返回是注册的进程在收到相关信息后,自动做出反应的机制,由回调函数实现。错误是信号的一种,是注册进程错误处理机制之一。
        服务:服务(Services)是进程注册的抽象。进程注册某个地址后,即可获得对应总线的服务。D-Bus提供了服务查询接口,进程可通过该接口查询某个服务是否存在。或者在服务结束时自动收到来自系统的消息。

        建立服务的流程:
        ----------------------------------
            建立一个dbus连接之后 -- dbus_bus_get(),为这个dbus连接(DbusConnection)起名 -- dbus_bus_request_name(),这个名字将会成为我们在后续进行远程调用的时候的服务名,然后我们进入监听循环 -- dbus_connection_read_write()。在循环中,我们从总线上取出消息 -- dbus_connection_pop_message(),并通过比对消息中的方法接口名和方法名 -- dbus_message_is_method_call(),如果一致,那么我们跳转到相应的处理中去。在相应的处理中,我们会从消息中取出远程调用的参数。并且建立起回传结果的通路 -- reply_to_method_call()。回传动作本身等同于一次不需要等待结果的远程调用。
        发送信号的流程:
        ----------------------------------
            建立一个dbus连接之后,为这个dbus连接起名,建立一个发送信号的通道,注意,在建立通道的函数中,需要我们填写该信号的接口名和信号名 -- dbus_message_new_signal()。然后我们把信号对应的相关参数压进去 -- dbus_message_iter_init_append(); dbus_message_iter_append_basic()。然后就可以启动发送了 -- dbus_connection_send(); dbus_connection_flush。
        进行一次远程调用的流程:
        ----------------------------------
            建立好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()。也就达成了我们进行本次远程调用的目的了。
        信号接收流程:
        ----------------------------------
            建立一个dbus连接之后,为这个dbus连接起名,为我们将要进行的消息循环添加匹配条件(就是通过信号名和信号接口名来进行匹配控制的) -- dbus_bus_add_match()。我们进入等待循环后,只需要对信号名,信号接口名进行判断就可以分别处理各种信号了。在各个处理分支上。我们可以分离出消息中的参数。对参数类型进行判断和其他的处理。
        dbus_connection_read_write()
        --------------------------------------
            As long as the connection is open, this function will block until it can read or write, then read or write, then return #TRUE.
            If the connection is closed, the function returns #FALSE.
        dbus_connection_pop_message()
        --------------------------------------
            Returns the first-received message from the incoming message queue, removing it from the queue. The caller owns a reference to the returned message. If the queue is empty, returns #NULL.
        dbus_connection_send()
        --------------------------------------
            Adds a message to the outgoing message queue. Does not block to write the message to the network; that happens asynchronously. To force the message to be written, call dbus_connection_flush(). Because this only queues the message, the only reason it can
        fail is lack of memory. Even if the connection is disconnected, no error will be returned.
            @param connection the connection.
            @param message the message to write.
            @param serial return location for message serial, or #NULL if you don't care
            @returns #TRUE on success.
        dbus_connection_send_with_reply()
        --------------------------------------
            Queues a message to send, as with dbus_connection_send(), but also returns a #DBusPendingCall used to receive a reply to the message. If no reply is received in the given timeout_milliseconds, this function expires the pending reply and generates a synthetic error reply (generated in-process, not by the remote application) indicating that a timeout occurred.
            A #DBusPendingCall will see a reply message before any filters or registered object path handlers. See dbus_connection_dispatch() for details on when handlers are run.
            A #DBusPendingCall will always see exactly one reply message, unless it's cancelled with dbus_pending_call_cancel().
            If #NULL is passed for the pending_return, the #DBusPendingCall will still be generated internally, and used to track the message reply timeout. This means a timeout error will occur if no reply arrives, unlike with dbus_connection_send().
            If -1 is passed for the timeout, a sane default timeout is used. -1 is typically the best value for the timeout for this reason, unless you want a very short or very long timeout. There is no way to avoid a timeout entirely, other than passing INT_MAX for the
        timeout to mean "very long timeout." libdbus clamps an INT_MAX timeout down to a few hours timeout though.
            @warning if the connection is disconnected, the #DBusPendingCall will be set to #NULL, so be careful with this.
            @param connection the connection
            @param message the message to send
            @param pending_return return location for a #DBusPendingCall object, or #NULL if connection is disconnected
            @param timeout_milliseconds timeout in milliseconds or -1 for default
            @returns #FALSE if no memory, #TRUE otherwise.
        dbus_message_is_signal()
        --------------------------------------
            Checks whether the message is a signal with the given interface and member fields. If the message is not #DBUS_MESSAGE_TYPE_SIGNAL, or has a different interface or member field, returns #FALSE.
        dbus_message_iter_init()
        --------------------------------------
            Initializes a #DBusMessageIter for reading the arguments of the message passed in.
        dbus_message_iter_next()
        --------------------------------------
            Moves the iterator to the next field, if any. If there's no next field, returns #FALSE. If the iterator moves forward, returns #TRUE.
        dbus_message_iter_get_arg_type()
        --------------------------------------
            Returns the argument type of the argument that the message iterator points to. If the iterator is at the end of the message, returns #DBUS_TYPE_INVALID.
        dbus_message_iter_get_basic()
        --------------------------------------
            Reads a basic-typed value from the message iterator. Basic types are the non-containers such as integer and string.
        dbus_message_new_signal()
        --------------------------------------
            Constructs a new message representing a signal emission. Returns #NULL if memory can't be allocated for the message. A signal is identified by its originating object path, interface, and the name of the signal.
            Path, interface, and signal name must all be valid (the D-Bus specification defines the syntax of these fields).
            @param path the path to the object emitting the signal
            @param interface the interface the signal is emitted from
            @param name name of the signal
            @returns a new DBusMessage, free with dbus_message_unref()
        dbus_message_iter_init_append()
        --------------------------------------
            Initializes a #DBusMessageIter for appending arguments to the end of a message.
            @param message the message
            @param iter pointer to an iterator to initialize
        dbus_message_iter_append_basic()
        --------------------------------------
            Appends a basic-typed value to the message. The basic types are the non-container types such as integer and string.
            @param iter the append iterator
            @param type the type of the value
            @param value the address of the value
            @returns #FALSE if not enough memory
        dbus_message_new_method_call()
        --------------------------------------
            Constructs a new message to invoke a method on a remote object. Returns #NULL if memory can't be allocated for the message. The destination may be #NULL in which case no destination is set; this is appropriate when using D-Bus in a peer-to-peer context (no message bus). The interface may be #NULL, which means that if multiple methods with the given name exist it is undefined which one will be invoked.
            The path and method names may not be #NULL.
            Destination, path, interface, and method name can't contain any invalid characters (see the D-Bus specification).
            @param destination name that the message should be sent to or #NULL
            @param path object path the message should be sent to
            @param interface interface to invoke method on, or #NULL
            @param method method to invoke
            @returns a new DBusMessage, free with dbus_message_unref()
        dbus_bus_get()
        --------------------------------------
            Connects to a bus daemon and registers the client with it. If a connection to the bus already exists, then that connection is returned. The caller of this function owns a reference to the bus.
            @param type bus type
            @param error address where an error can be returned.
            @returns a #DBusConnection with new ref
        dbus_bus_request_name()
        --------------------------------------
            Asks the bus to assign the given name to this connection by invoking the RequestName method on the bus.
            First you should know that for each bus name, the bus stores a queue of connections that would like to own it. Only one owns it at a time - called the primary owner. If the primary owner releases the name or disconnects, then the next owner in the queue atomically takes over.
            So for example if you have an application org.freedesktop.TextEditor and multiple instances of it can be run, you can have all of them sitting in the queue. The first one to start up will receive messages sent to org.freedesktop.TextEditor, but if that one exits another will become the primary owner and receive messages.
            The queue means you don't need to manually watch for the current owner to disappear and then request the name again.
            @param connection the connection
            @param name the name to request
            @param flags flags
            @param error location to store the error
            @returns a result code, -1 if error is set
            给DBusConnection起名字(命名) -- 两个相互通信的连接(connection)不能同名
            命名规则: xxx.xxx (zeng.xiaolong)
        dbus_bus_add_match()
        --------------------------------------
            Adds a match rule to match messages going through the message bus. The "rule" argument is the string form of a match rule.
            @param connection connection to the message bus
            @param rule textual form of match rule
            @param error location to store any errors
        dbus_pending_call_block()
        --------------------------------------
            Block until the pending call is completed. The blocking is as with dbus_connection_send_with_reply_and_block(); it does not enter the main loop or process other messages, it simply waits for the reply in question.
            If the pending call is already completed, this function returns immediately.
            @todo when you start blocking, the timeout is reset, but it should really only use time remaining since the pending call was created. This requires storing timestamps instead of intervals in the timeout
            @param pending the pending call
        dbus_pending_call_steal_reply()
        --------------------------------------
            Gets the reply, or returns #NULL if none has been received yet. Ownership of the reply message passes to the caller. This function can only be called once per pending call, since the reply message is tranferred to the caller.
            @param pending the pending call
            @returns the reply message or #NULL.

        安装D-Bus可在其官方网站下载源码编译,地址为http://dbus.freedesktop.org。或者在终端上输入下列指令:
            yum install dbus dbus-devel dbus-doc
        安装后,头文件位于"/usr/include/dbus-<版本号>/dbus"目录中,编译使用D-Bus的程序时需加入编译指令"`pkg-config --cflags --libs dbus-1`"。

    3.  D-Bus的用例
        在使用GNOME桌面环境的Linux系统中,通常用GLib库提供的函数来管理总线。在测试下列用例前,首先需要安装GTK+开发包(见22.3节)并配置编译环境。该用例一共包含两个程序文件,每个程序文件需单独编译成为可执行文件。

        1.消息发送程序
        "dbus-ding-send.c"程序每秒通过会话总线发送一个参数为字符串Ding!的信号。该程序的源代码如下:

            #include <glib.h>                               // 包含glib库  
            #include <dbus/dbus-glib.h>                     // 包含
            glib库中D-Bus管理库  
            #include <stdio.h>
            static gboolean send_ding(DBusConnection *bus);// 定义发送消息函数的原型  
            int main ()  
            {  
               GMainLoop *loop;                             // 定义一个事件循环对象的指针  
               DBusConnection *bus;                         // 定义总线连接对象的指针  
               DBusError error;                             // 定义D-Bus错误消息对象  
               loop = g_main_loop_new(NULL, FALSE);         // 创建新事件循环对象  
               dbus_error_init (&error);                    // 将错误消息对象连接到D-Bus  
                                                            // 错误消息对象  
               bus = dbus_bus_get(DBUS_BUS_SESSION, &error);// 连接到总线  
               if (!bus) {                                      // 判断是否连接错误  
                        g_warning("连接到D-Bus失败: %s", error.message);  // 使用GLib输出错误警告信息  
                  dbus_error_free(&error);                         // 清除错误消息  
                  return 1;  
               }  
               dbus_connection_setup_with_g_main(bus, NULL);// 将总线设为接收GLib事件循环  
               g_timeout_add(1000, (GSourceFunc)send_ding, bus);  // 每隔1000ms调用一次send_ding()函数  // 将总线指针作为参数  
               g_main_loop_run(loop);                           // 启动事件循环  
               return 0;  
            }  
            static gboolean send_ding(DBusConnection *bus)  // 定义发送消息函数的细节  
            {  
               DBusMessage *message;                        // 创建消息对象指针  
               message = dbus_message_new_signal("/com/burtonini/dbus/ding",   
                                                   "com.burtonini.dbus.Signal",  
                                                   "ding");     // 创建消息对象并标识路径  
               dbus_message_append_args(message,  
                                        DBUS_TYPE_STRING, "ding!",  
                                        DBUS_TYPE_INVALID);     //将字符串Ding!定义为消息  
               dbus_connection_send(bus, message, NULL);    // 发送该消息  
               dbus_message_unref(message);                 // 释放消息对象  
               g_print("ding!\n");                          // 该函数等同与标准输入输出                                    
               return TRUE;  
            }

        main()函数创建一个GLib事件循环,获得会话总线的一个连接,并将D-Bus事件处理集成到GLib事件循环之中。然后它创建了一个名为send_ding()函数作为间隔为一秒的计时器,并启动事件循环。send_ding()函数构造一个来自于对象路径"/com/burtonini/dbus/ding"和接口"com.burtonini.dbus.Signal"的新的Ding信号。然后,字符串Ding!作为参数添加到信号中并通过总线发送。在标准输出中会打印一条消息以让用户知道发送了一个信号。

        2.消息接收程序
        dbus-ding-listen.c程序通过会话总线接收dbus-ding-send.c程序发送到消息。该程序的源代码如下:

            #include <glib.h>                               // 包含glib库  
            #include <dbus/dbus-glib.h>                     // 包含glib库中D-Bus管理库  
            static DBusHandlerResult signal_filter      // 定义接收消息函数的原型  
                  (DBusConnection *connection, DBusMessage *message, void *user_data);  
            int main()  
            {  
                            GMainLoop *loop;                                 // 定义一个事件循环对象的指针  
                            DBusConnection *bus;                             // 定义总线连接对象的指针  
                            DBusError error;                                 // 定义D-Bus错误消息对象  
                            loop = g_main_loop_new(NULL, FALSE);             // 创建新事件循环对象  
                            dbus_error_init(&error);                         // 将错误消息对象连接到D-Bus  
                                                                                  // 错误消息对象  
                            bus = dbus_bus_get(DBUS_BUS_SESSION, &error);    // 连接到总线  
                            if (!bus) {                                          // 判断是否连接错误  
                                    g_warning("连接到D-Bus失败: %s", error.message);  // 使用GLib输出错误警告信息  
                                    dbus_error_free(&error);                      // 清除错误消息  
                                    return 1;  
                            }  
                   dbus_connection_setup_with_g_main(bus, NULL);  // 将总线设为接收GLib事件循环  
                            dbus_bus_add_match(bus, "type='signal',interface='com.burtonini.dbus.Signal'");  // 定义匹配器  
                            dbus_connection_add_filter(bus, signal_filter, loop, NULL);  // 调用函数接收消息  
                            g_main_loop_run(loop);                   // 启动事件循环  
                            return 0;  
            }  
            static DBusHandlerResult                    // 定义接收消息函数的细节  
            signal_filter (DBusConnection *connection,
            DBusMessage *message, void *user_data)  
            {  
               GMainLoop *loop = user_data;             // 定义事件循环对象的指针,并与主函数中的同步  
               if (dbus_message_is_signal
                           (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,"Disconnected")){// 接收连接成功消息,判断是否连接失败     
                  g_main_loop_quit (loop);              // 退出主循环  
                  return DBUS_HANDLER_RESULT_HANDLED;  
               }  
               if (dbus_message_is_signal
                           (message, "com.burtonini.dbus.Signal",   "Ping")) {  // 指定消息对象路径,判断是否成功  
                  DBusError error;                // 定义错误对象  
                  char *s;  
                        dbus_error_init(&error);         // 将错误消息对象连接到D-Bus错误  
                                                    // 消息对象  
                  if (dbus_message_get_args                 
                             (message, &error, DBUS_TYPE_STRING, &s,DBUS_TYPE_INVALID)) { // 接收消息,并判断是否有错误  
                     g_print("接收到的消息是: %s\n", s);   // 输出接收到的消息  
                     dbus_free (s);                     // 清除该消息  
                  } else{                               // 有错误时执行下列语句  
                     g_print("消息已收到,但有错误提示: %s\n", error.message);  
                     dbus_error_free (&error);  
                  }  
                  return DBUS_HANDLER_RESULT_HANDLED;  
               }  
               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;  
            }

        该程序侦听dbus-ping-send.c程序正在发出的信号。main()函数和前面一样启动,创建一个到总线的连接。然后它声明愿意在使用com.burtonini.dbus.Signal接口的信号被发送时得到通知,将signal_filter()函数设置为通知函数,然后进入事件循环。当满足匹配的消息被发送时,signal_func()函数会被调用。

        如果需要确定在接收消息时如何处理,可通过检测消息头实现。若收到的消息为总线断开信号,则主事件循环将被终止,因为监听的总线已经不存在了。若收到其他的消息,首先将收到的消息与期待的消息进行比较,两者相同则输出其中参数,并退出程序。两者不相同则告知总线并没有处理该消息,这样消息会继续保留在总线中供别的程序处理。
    展开全文
  • dbus接口

    2010-03-16 12:59:00
    建立服务的流程:---------------------------------- 建立一个dbus连接之后 -- dbus_bus_get(),为这个dbus连接(DbusConnection)起名 -- dbus_bus_request_name(),这个名字将会成为我们在后续进行远程调用的时候的...

    建立服务的流程:
    ----------------------------------
        建立一个dbus连接之后 -- dbus_bus_get(),为这个dbus连接(DbusConnection)起名 -- dbus_bus_request_name(),这个名字将会成为我们在后续进行远程调用的时候的服务名,然后我们进入监听循环 -- dbus_connection_read_write()。在循环中,我们从总线上取出消息 -- dbus_connection_pop_message(),并通过比对消息中的方法接口名和方法名 -- dbus_message_is_method_call(),如果一致,那么我们跳转到相应的处理中去。在相应的处理中,我们会从消息中取出远程调用的参数。并且建立起回传结果的通路 -- reply_to_method_call()。回传动作本身等同于一次不需要等待结果的远程调用。


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


    进行一次远程调用的流程:
    ----------------------------------
        建立好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()。也就达成了我们进行本次远程调用的目的了。


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


    dbus_connection_read_write()
    --------------------------------------
        As long as the connection is open, this function will block until it can read or write, then read or write, then return #TRUE.
        If the connection is closed, the function returns #FALSE.


    dbus_connection_pop_message()
    --------------------------------------
        Returns the first-received message from the incoming message queue, removing it from the queue. The caller owns a reference to the returned message. If the queue is empty, returns #NULL.


    dbus_connection_send()
    --------------------------------------
        Adds a message to the outgoing message queue. Does not block to write the message to the network; that happens asynchronously. To force the message to be written, call dbus_connection_flush(). Because this only queues the message, the only reason it can
    fail is lack of memory. Even if the connection is disconnected, no error will be returned.
        @param connection the connection.
        @param message the message to write.
        @param serial return location for message serial, or #NULL if you don't care
        @returns #TRUE on success.


    dbus_connection_send_with_reply()
    --------------------------------------
        Queues a message to send, as with dbus_connection_send(), but also returns a #DBusPendingCall used to receive a reply to the message. If no reply is received in the given timeout_milliseconds, this function expires the pending reply and generates a synthetic error reply (generated in-process, not by the remote application) indicating that a timeout occurred.

        A #DBusPendingCall will see a reply message before any filters or registered object path handlers. See dbus_connection_dispatch() for details on when handlers are run.

        A #DBusPendingCall will always see exactly one reply message, unless it's cancelled with dbus_pending_call_cancel().

        If #NULL is passed for the pending_return, the #DBusPendingCall will still be generated internally, and used to track the message reply timeout. This means a timeout error will occur if no reply arrives, unlike with dbus_connection_send().
       
        If -1 is passed for the timeout, a sane default timeout is used. -1 is typically the best value for the timeout for this reason, unless you want a very short or very long timeout. There is no way to avoid a timeout entirely, other than passing INT_MAX for the
    timeout to mean "very long timeout." libdbus clamps an INT_MAX timeout down to a few hours timeout though.

        @warning if the connection is disconnected, the #DBusPendingCall will be set to #NULL, so be careful with this.
       
        @param connection the connection
        @param message the message to send
        @param pending_return return location for a #DBusPendingCall object, or #NULL if connection is disconnected
        @param timeout_milliseconds timeout in milliseconds or -1 for default
        @returns #FALSE if no memory, #TRUE otherwise.




    dbus_message_is_signal()
    --------------------------------------
        Checks whether the message is a signal with the given interface and member fields. If the message is not #DBUS_MESSAGE_TYPE_SIGNAL, or has a different interface or member field, returns #FALSE.


    dbus_message_iter_init()
    --------------------------------------
        Initializes a #DBusMessageIter for reading the arguments of the message passed in.


    dbus_message_iter_next()
    --------------------------------------
        Moves the iterator to the next field, if any. If there's no next field, returns #FALSE. If the iterator moves forward, returns #TRUE.


    dbus_message_iter_get_arg_type()
    --------------------------------------
        Returns the argument type of the argument that the message iterator points to. If the iterator is at the end of the message, returns #DBUS_TYPE_INVALID.


    dbus_message_iter_get_basic()
    --------------------------------------
        Reads a basic-typed value from the message iterator. Basic types are the non-containers such as integer and string.


    dbus_message_new_signal()
    --------------------------------------
        Constructs a new message representing a signal emission. Returns #NULL if memory can't be allocated for the message. A signal is identified by its originating object path, interface, and the name of the signal.

        Path, interface, and signal name must all be valid (the D-Bus specification defines the syntax of these fields).
       
        @param path the path to the object emitting the signal
        @param interface the interface the signal is emitted from
        @param name name of the signal
        @returns a new DBusMessage, free with dbus_message_unref()


    dbus_message_iter_init_append()
    --------------------------------------
        Initializes a #DBusMessageIter for appending arguments to the end of a message.
        @param message the message
        @param iter pointer to an iterator to initialize


    dbus_message_iter_append_basic()
    --------------------------------------
        Appends a basic-typed value to the message. The basic types are the non-container types such as integer and string.
        @param iter the append iterator
        @param type the type of the value
        @param value the address of the value
        @returns #FALSE if not enough memory


    dbus_message_new_method_call()
    --------------------------------------
        Constructs a new message to invoke a method on a remote object. Returns #NULL if memory can't be allocated for the message. The destination may be #NULL in which case no destination is set; this is appropriate when using D-Bus in a peer-to-peer context (no message bus). The interface may be #NULL, which means that if multiple methods with the given name exist it is undefined which one will be invoked.

        The path and method names may not be #NULL.

        Destination, path, interface, and method name can't contain any invalid characters (see the D-Bus specification).

        @param destination name that the message should be sent to or #NULL
        @param path object path the message should be sent to
        @param interface interface to invoke method on, or #NULL
        @param method method to invoke

        @returns a new DBusMessage, free with dbus_message_unref()


    dbus_bus_get()
    --------------------------------------
        Connects to a bus daemon and registers the client with it. If a connection to the bus already exists, then that connection is returned. The caller of this function owns a reference to the bus.
        @param type bus type
        @param error address where an error can be returned.
        @returns a #DBusConnection with new ref


    dbus_bus_request_name()
    --------------------------------------
        Asks the bus to assign the given name to this connection by invoking the RequestName method on the bus.

        First you should know that for each bus name, the bus stores a queue of connections that would like to own it. Only one owns it at a time - called the primary owner. If the primary owner releases the name or disconnects, then the next owner in the queue atomically takes over.

        So for example if you have an application org.freedesktop.TextEditor and multiple instances of it can be run, you can have all of them sitting in the queue. The first one to start up will receive messages sent to org.freedesktop.TextEditor, but if that one exits another will become the primary owner and receive messages.

        The queue means you don't need to manually watch for the current owner to disappear and then request the name again.
       
        @param connection the connection
        @param name the name to request
        @param flags flags
        @param error location to store the error
        @returns a result code, -1 if error is set

        给DBusConnection起名字(命名) -- 两个相互通信的连接(connection)不能同名
        命名规则: xxx.xxx (zeng.xiaolong)


    dbus_bus_add_match()
    --------------------------------------
        Adds a match rule to match messages going through the message bus. The "rule" argument is the string form of a match rule.
        @param connection connection to the message bus
        @param rule textual form of match rule
        @param error location to store any errors





    dbus_pending_call_block()
    --------------------------------------
        Block until the pending call is completed. The blocking is as with dbus_connection_send_with_reply_and_block(); it does not enter the main loop or process other messages, it simply waits for the reply in question.

        If the pending call is already completed, this function returns immediately.

        @todo when you start blocking, the timeout is reset, but it should really only use time remaining since the pending call was created. This requires storing timestamps instead of intervals in the timeout

        @param pending the pending call


    dbus_pending_call_steal_reply()
    --------------------------------------
        Gets the reply, or returns #NULL if none has been received yet. Ownership of the reply message passes to the caller. This function can only be called once per pending call, since the reply message is tranferred to the caller.

        @param pending the pending call
        @returns the reply message or #NULL.

    展开全文
  • //步骤3:通知D-Bus daemon,希望监听来行接口test.signal.Type的信号 dbus_bus_add_match(connection,"type='signal',interface='test.signal.Type'",&err); //实际需要发送东西给daemon来通知希望监听的内容,所以...
  • DBus研究笔记(一)

    千次阅读 2013-08-08 20:53:33
    常用DBusConnection* dbus_bus_get(DBusBusType, DBusError*)系列函数来与bus daemon建立连接。DBusBusType为需要连接的总线类型有系统总线,会话总线,和DBUS_BUS_STARTER。系统总线顾名思义在整个系统级别都有效,...
  • 建立服务的流程:---------------------------------- 建立一个dbus连接之后 -- dbus_bus_get(),为这个dbus连接(DbusConnection)起名 -- dbus_bus_request_name(),这个名字将会成为我们在后续进行远程调用的时候的...
  • dbus基本接口(转)

    2010-08-12 10:50:00
    http://www.haohaoxuexi.com/Institute/Details.php?Id=9896<br /> ... 建立一个dbus连接之后 -- dbus_bus_get(),为这个dbus连接(DbusConnection)起名 -- dbus_bus_request_name(),这个名字将会成为我们在
  • DBUS

    万次阅读 2011-03-22 16:40:00
    dbus基本接口/** Example low-level D-Bus code.* Written by Matthew Johnson ** This code has been released into the Public Domain.* You may do whatever you like with it.*/#include #inclu
  • DBus的理解与应用

    2021-07-08 10:26:42
    DBus 连接 (通用部分) DBus Name 是用来给应用程序进行标识自己的,所以每当程序连上 DBus Daemon 后,就会分配到一个 Unique ...conn = dbus_bus_get(DBUS_BUS_SESSION, &err); if (dbus_error_is_set(&err))
  • Dbus

    2019-12-26 14:09:03
    DBus (Desktop Bus) 是一种 IPC 机制, 由 freedesktop.org 项目提供, 用于进程间通信或进程与内核的通信 tips: IPC机制还有 fifo管道, share memory, semaphore, message queue, socket … DBus三层架构: 底层...
  • Linux DBUS服务器端程序

    2019-12-19 18:03:06
    DBus 服务器端接收方式 DBus 服务器端用来接收signal和method调用。从收集的资料中发现,主要有三种接收方式。 一,采用while循环,监听dbus_connection_read_write()...test.signal.server(bus name) | ----t...
  • blueZ5的dbus API开发

    千次阅读 2019-12-20 15:17:21
    最近我们领导让我做了个基于blueZ5... 首先,对于dbus的远程调用来说每次调用dbus_message_new_method_call函数来构造方法信息时都需要传入bus name,object path,interface,method name四个参数。对于bus name,i...
  • DBus通讯

    2019-10-08 16:37:20
    linux下进程间通信的方式主要有Pipe(管道),FIFO(命名管道),信号,共享内存,消息队列,信号灯等,这些方式各有 各得特点,如管道是linux下命令行中常用的,用于父子进程的通信。...网上有一篇叫“D-Bus Tuto...
  • DBUS学习-DBUS实例

    2021-04-02 11:52:34
    一、原生DBUS实例 原生dbus客户端代码和服务端代码: client.c折叠源码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #...
  • struct bus_type使用方法

    2012-09-24 11:13:56
     我们还看到了一个和总线驱动相关的结构体bus_type。这个结构体的定义在include/linux/device.h中。本节先简单介绍结构体中的成员,再对每个成员作详细描述。     struct bus_type{    const char *...
  • 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是一个...
  • dbus 学习

    2019-01-02 19:14:01
    和菜鸟一起学linux之DBUS基础学习记录 D-Bus三层架构 D-Bus是一个为应用程序间通信的消息总线系统, 用于进程之间的通信。它是个3层架构的IPC 系统,包括: 1、函数库libdbus ,用于两个应用程序互相联系和交互...
  • DBUS基础知识

    2014-05-20 10:36:51
    DBUS基础知识 1. 进程间使用D-Bus通信 D-Bus是一种高级的进程间通信机制,它由freedesktop.org项目提供,使用GPL许可证发行。D-Bus最主要的用途是在Linux桌面环境为进程提供通信,同时能将Linux桌面环境和...
  • dbus介绍与例子

    万次阅读 多人点赞 2015-08-08 16:50:45
     网上很多关于dbus的帖子都是基于dbus-glib或者QT D-bus的,直接使用dbus的教程比较少。也难怪,因为连D-bus的官网都说:"If you use this low-level API directly, you're signing up for some pain."  但实际上...
  • dbus example

    千次阅读 2010-05-19 19:15:00
    我们继续学习D-Bus,参考http://dbus.freedesktop.org/doc/dbus/libdbus-tutorial.html ,相关的API接口reference参考http://dbus.freedesktop.org/doc/dbus/api/html/modules.html 。从底层,即libdbus学习如何...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 569
精华内容 227
关键字:

dbus_bus_add_match