• DBus在Hi3515中的移植


    1.基础环境:

    虚拟机:VMware Workstation8  操作系统:Ubuntu12.04  

    交叉编译工具 arm-hismall-linux

    以下为需要安装的库:

    DBus版本:1.6.4    glib版本:2.32.4    libxml2版本:2.6.8   gettext版本:0.18

    其中glib与gettext直接运行./configuire、make、make install进行安装

    DBus需要libxml2动态链接库的支持,所以libxml2需要交叉编译 ./configure --host=arm-hismall-linux 、make、 make install 来安装

    可能遇见的问题:

    configure error: you must have either have gettext support in your C library, or use the***

    编译glib时,先安装好gettext,遇到上述问题,运行ldconfig

    2.交叉编译DBus

    2.1 执行configure

    ./configure --host=arm-hismall-linux --with-xml=libxml (使用libxml解析器,如不用--with会遇到 expand.h:No such file or directory)

    可能遇到的问题:

    encoding.h:28:19: iconv.h: No such file or director

    此种情况为glibxml2的版本太低。

    libxml2.so: could not read symbols: File in wrong format

    需要交叉编译libxml2库,并安装

    checking for libxml-2.0 >= 2.6.0... configure: error: Explicitly requested libxml but libxml not found

    其实已经安装上 libxml2 了的,这里只是一环境变量没有设置好而已。
    解决办法:

    echo $PKG_CONFIG_PATH
    (1)确定 /usr/local/libxml2/lib/pkgconfig 目录下有 libxml-2.0.pc
    (2)export PKG_CONFIG_PATH=/usr/local/libxml2/lib/pkgconfig:$PKG_CONFIG_PATH
    (3)再./configure一次,到没有出现错误就OK了。

    2.2 执行make

    可能遇到问题:

    arm-hisi-linux/bin/ld: cannot find -lz

    缺少libz库 sudo apt-get install lib64z1-dev

    bus.c:694: undefined reference to `bus_set_watched_dirs'

    缺少函数bus_set_watched_dirs的定义,具体可见  https://bugs.freedesktop.org/show_bug.cgi?id=33001

    修改bus-1.6.4/bus/dir-watch-dnotify.c  如下为部分代码  (//add为添加部分)

     1 #include <dbus/dbus-internals.h>
     2 #include <dbus/dbus-list.h>
     3 #include "dir-watch.h"     //add 
     4  
     5 #define MAX_DIRS_TO_WATCH 128
     6 
     7 /* use a static array to avoid handling OOM */
     8 static int fds[MAX_DIRS_TO_WATCH];
     9 static int num_fds = 0;
    10 void bus_watch_directory(const char *dir, BusContext *context);    //add
    11 //add function
    12 void bus_set_watched_dirs(BusContext *context,DBusList **directories)
    13 {
    14    DBusList *link=_dbus_list_get_first_link(directories);
    15    while(link!=NULL)
    16    {
    17      bus_watch_directory(link->data,context);
    18      link=_dbus_list_get_next_link(directories,link);
    19    }
    20 }

    修改bus-1.6.4/bus/bus.c  添加头文件

    #include "dir-watch.h"

    2.3 sudo make install

    3. 运行dbus-daemon

    以上执行完成后,可以在bus-1.6.4/bus/目录下找到dbus-daemon,即为交叉编译后的dbus应用;bus-1.6.4/tools/目录下找到dbus-launch,为启动并配置dbus-daemon的程序,编写脚本dbus_run来启动dbus-launch

    #!/bin/sh
    if test -z "$DBUS_SESSION_BUS_ADDRESS" ; then
    ## if not found, launch a new one
    eval `dbus-launch --sh-syntax --exit-with-session`
    echo "D-Bus per-session daemon address is: $DBUS_SESSION_BUS_ADDRESS"
    fi

    将dbus-daemon、dbus-launch放到开发板上/usr/bin/目录下 将libxml2.so.2 放到/usr/lib/ 下

    在开发板上运行dbus-daemon进行测试

    可能遇到的问题:

    # dbus-daemon --system

    Failed to start message bus: Failed to open "/usr/local/etc/dbus-1/system.conf":
    No such file or directory

    于是我又到dbus-1.6.4/bus中找到system.conf  session.conf(针对--session参数)

    # dbus-daemon --system

    Failed to start message bus: Failed to open :".....system.d" No such file or directory

    于是响应目录下建了个system.d文件夹 (创建session.d 针对--session参数)

    # dbus-daemon --system

    Failed to start message bus: Failed to bind socket "/var/run/dbus/system_bus_soc ket

    No such file or directory

    在相应目录下创建system_bus_socket,结果

    # dbus-daemon --system

    Failed to start message bus: Failed to bind socket "/var/run/dbus/system_bus_soc ket:Address already in use

    郁闷,删掉system_bus_socket,只留/var/run/dbus/

    # dbus-daemon --system

    Failed to start message bus:Could not get UID and GID for username "messagebus"

    通过添加用户解决 adduser messagebus 密码设为dbus 也可以在/etc/passwd后添加 

    messagebus:$1$$YwM2vWXS3L4EbCfJU4I7N0:500:500:Linux User,,,:/home/messagebus:/bi   //为adduser messagebus命令生成

    到这一步dbus-daemon可正常运行

    4.编写应用测试DBus

    4.1 gcc编译

    在网上找了一段代码,感觉还不错 代码贴出如下 引用地址:http://hi.baidu.com/zengzhaonong/item/5143e33eb880abfedf222173

      1 /*
      2 * Example low-level D-Bus code.
      3 * Written by Matthew Johnson <dbus@matthew.ath.cx>
      4 *
      5 * This code has been released into the Public Domain.
      6 * You may do whatever you like with it.
      7 */
      8 #include <dbus/dbus.h>
      9 #include <stdbool.h>
     10 #include <unistd.h>
     11 #include <stdio.h>
     12 #include <stdlib.h>
     13 
     14 /**
     15 * Connect to the DBUS bus and send a broadcast signal
     16 */
     17 void sendsignal(char* sigvalue)
     18 {
     19    DBusMessage* msg;
     20    DBusMessageIter args;
     21    DBusConnection* conn;
     22    DBusError err;
     23    int ret;
     24    dbus_uint32_t serial = 0;
     25 
     26    printf("Sending signal with value %s\n", sigvalue);
     27 
     28    // initialise the error value
     29    dbus_error_init(&err);
     30 
     31    // connect to the DBUS system bus, and check for errors
     32    conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
     33    if (dbus_error_is_set(&err)) {
     34       fprintf(stderr, "Connection Error (%s)\n", err.message);
     35       dbus_error_free(&err);
     36    }
     37    if (NULL == conn) {
     38       exit(1);
     39    }
     40 
     41    // register our name on the bus, and check for errors
     42    ret = dbus_bus_request_name(conn, "test.signal.source", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
     43    if (dbus_error_is_set(&err)) {
     44       fprintf(stderr, "Name Error (%s)\n", err.message);
     45       dbus_error_free(&err);
     46    }
     47    if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
     48       exit(1);
     49    }
     50 
     51    // create a signal & check for errors
     52    msg = dbus_message_new_signal("/test/signal/Object", // object name of the signal
     53                                  "test.signal.Type",    // interface name of the signal
     54                                  "Test");               // name of the signal
     55    if (NULL == msg)
     56    {
     57       fprintf(stderr, "Message Null\n");
     58       exit(1);
     59    }
     60 
     61    // append arguments onto signal
     62    dbus_message_iter_init_append(msg, &args);
     63    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
     64       fprintf(stderr, "Out Of Memory!\n");
     65       exit(1);
     66    }
     67 
     68    // send the message and flush the connection
     69    if (!dbus_connection_send(conn, msg, &serial)) {
     70       fprintf(stderr, "Out Of Memory!\n");
     71       exit(1);
     72    }
     73    dbus_connection_flush(conn);
     74   
     75    printf("Signal Sent\n");
     76   
     77    // free the message
     78    dbus_message_unref(msg);
     79 }
     80 
     81 /**
     82 * Call a method on a remote object
     83 */
     84 void query(char* param)
     85 {
     86    DBusMessage* msg;
     87    DBusMessageIter args;
     88    DBusConnection* conn;
     89    DBusError err;
     90    DBusPendingCall* pending;
     91    int ret;
     92    bool stat;
     93    dbus_uint32_t level;
     94 
     95    printf("Calling remote method with %s\n", param);
     96 
     97    // initialiset the errors
     98    dbus_error_init(&err);
     99 
    100    // connect to the system bus and check for errors
    101    conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
    102    if (dbus_error_is_set(&err)) {
    103       fprintf(stderr, "Connection Error (%s)\n", err.message);
    104       dbus_error_free(&err);
    105    }
    106    if (NULL == conn) {
    107       exit(1);
    108    }
    109 
    110    // request our name on the bus
    111    ret = dbus_bus_request_name(conn, "test.method.caller", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
    112    if (dbus_error_is_set(&err)) {
    113       fprintf(stderr, "Name Error (%s)\n", err.message);
    114       dbus_error_free(&err);
    115    }
    116    if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
    117       exit(1);
    118    }
    119 
    120    // create a new method call and check for errors
    121    msg = dbus_message_new_method_call("test.method.server",// target for the method call
    122                                       "/test/method/Object", // object to call on
    123                                       "test.method.Type",    // interface to call on
    124                                       "Method");             // method name
    125    if (NULL == msg) {
    126       fprintf(stderr, "Message Null\n");
    127       exit(1);
    128    }
    129 
    130    // append arguments
    131    dbus_message_iter_init_append(msg, &args);
    132    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &param)) {
    133       fprintf(stderr, "Out Of Memory!\n");
    134       exit(1);
    135    }
    136   
    137    // send message and get a handle for a reply
    138    if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { // -1 is default timeout
    139       fprintf(stderr, "Out Of Memory!\n");
    140       exit(1);
    141    }
    142    if (NULL == pending) {
    143       fprintf(stderr, "Pending Call Null\n");
    144       exit(1);
    145    }
    146    dbus_connection_flush(conn);
    147   
    148    printf("Request Sent\n");
    149   
    150    // free message
    151    dbus_message_unref(msg);
    152   
    153    // block until we recieve a reply
    154    dbus_pending_call_block(pending);
    155 
    156    // get the reply message
    157    msg = dbus_pending_call_steal_reply(pending);
    158    if (NULL == msg) {
    159       fprintf(stderr, "Reply Null\n");
    160       exit(1);
    161    }
    162    // free the pending message handle
    163    dbus_pending_call_unref(pending);
    164 
    165    // read the parameters
    166    if (!dbus_message_iter_init(msg, &args))
    167       fprintf(stderr, "Message has no arguments!\n");
    168    else if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&args))
    169       fprintf(stderr, "Argument is not boolean!\n");
    170    else
    171       dbus_message_iter_get_basic(&args, &stat);
    172 
    173    if (!dbus_message_iter_next(&args))
    174       fprintf(stderr, "Message has too few arguments!\n");
    175    else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
    176       fprintf(stderr, "Argument is not int!\n");
    177    else
    178       dbus_message_iter_get_basic(&args, &level);
    179 
    180    printf("Got Reply: %d, %d\n", stat, level);
    181   
    182    // free reply
    183    dbus_message_unref(msg);  
    184 }
    185 
    186 
    187 void reply_to_method_call(DBusMessage* msg, DBusConnection* conn)
    188 {
    189    DBusMessage* reply;
    190    DBusMessageIter args;
    191    bool stat = true;
    192    dbus_uint32_t level = 21614;
    193    dbus_uint32_t serial = 0;
    194    char* param = "";
    195 
    196    // read the arguments
    197    if (!dbus_message_iter_init(msg, &args))
    198       fprintf(stderr, "Message has no arguments!\n");
    199    else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
    200       fprintf(stderr, "Argument is not string!\n");
    201    else
    202       dbus_message_iter_get_basic(&args, &param);
    203 
    204    printf("Method called with %s\n", param);
    205 
    206    // create a reply from the message
    207    reply = dbus_message_new_method_return(msg);
    208 
    209    // add the arguments to the reply
    210    dbus_message_iter_init_append(reply, &args);
    211    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &stat)) {
    212       fprintf(stderr, "Out Of Memory!\n");
    213       exit(1);
    214    }
    215    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &level)) {
    216       fprintf(stderr, "Out Of Memory!\n");
    217       exit(1);
    218    }
    219 
    220    // send the reply && flush the connection
    221    if (!dbus_connection_send(conn, reply, &serial)) {
    222       fprintf(stderr, "Out Of Memory!\n");
    223       exit(1);
    224    }
    225    dbus_connection_flush(conn);
    226 
    227    // free the reply
    228    dbus_message_unref(reply);
    229 }
    230 
    231 
    232 
    233 /**
    234 * Server that exposes a method call and waits for it to be called
    235 */
    236 void listen()
    237 {
    238    DBusMessage* msg;
    239    DBusMessage* reply;
    240    DBusMessageIter args;
    241    DBusConnection* conn;
    242    DBusError err;
    243    int ret;
    244    char* param;
    245 
    246    printf("Listening for method calls\n");
    247 
    248    // initialise the error
    249    dbus_error_init(&err);
    250   
    251    // connect to the bus and check for errors
    252    conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
    253    if (dbus_error_is_set(&err)) {
    254       fprintf(stderr, "Connection Error (%s)\n", err.message);
    255       dbus_error_free(&err);
    256    }
    257    if (NULL == conn) {
    258       fprintf(stderr, "Connection Null\n");
    259       exit(1);
    260    }
    261   
    262    // request our name on the bus and check for errors
    263    ret = dbus_bus_request_name(conn, "test.method.server",
    264                                DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
    265    if (dbus_error_is_set(&err)) {
    266       fprintf(stderr, "Name Error (%s)\n", err.message);
    267       dbus_error_free(&err);
    268    }
    269    if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
    270       fprintf(stderr, "Not Primary Owner (%d)\n", ret);
    271       exit(1);
    272    }
    273 
    274    // loop, testing for new messages
    275    while (true) {
    276       // non blocking read of the next available message
    277       dbus_connection_read_write(conn, 0);
    278       msg = dbus_connection_pop_message(conn);
    279 
    280       // loop again if we haven't got a message
    281       if (NULL == msg) {
    282          sleep(1);
    283          continue;
    284       }
    285      
    286       // check this is a method call for the right interface & method
    287       if (dbus_message_is_method_call(msg, "test.method.Type", "Method"))
    288          reply_to_method_call(msg, conn);
    289 
    290       // free the message
    291       dbus_message_unref(msg);
    292    }
    293 }
    294 
    295 
    296 
    297 /**
    298 * Listens for signals on the bus
    299 */
    300 void receive()
    301 {
    302    DBusMessage* msg;
    303    DBusMessageIter args;
    304    DBusConnection* conn;
    305    DBusError err;
    306    int ret;
    307    char* sigvalue;
    308 
    309    printf("Listening for signals\n");
    310 
    311    // initialise the errors
    312    dbus_error_init(&err);
    313   
    314    // connect to the bus and check for errors
    315    conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
    316    if (dbus_error_is_set(&err)) {
    317       fprintf(stderr, "Connection Error (%s)\n", err.message);
    318       dbus_error_free(&err);
    319    }
    320    if (NULL == conn) {
    321       exit(1);
    322    }
    323   
    324    // request our name on the bus and check for errors
    325    ret = dbus_bus_request_name(conn, "test.signal.sink", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
    326    if (dbus_error_is_set(&err)) {
    327       fprintf(stderr, "Name Error (%s)\n", err.message);
    328       dbus_error_free(&err);
    329    }
    330    if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
    331       exit(1);
    332    }
    333 
    334    // add a rule for which messages we want to see
    335    dbus_bus_add_match(conn, "type='signal',interface='test.signal.Type'", &err); // see signals from the given interface
    336    dbus_connection_flush(conn);
    337    if (dbus_error_is_set(&err)) {
    338       fprintf(stderr, "Match Error (%s)\n", err.message);
    339       exit(1);
    340    }
    341    printf("Match rule sent\n");
    342 
    343    // loop listening for signals being emmitted
    344    while (true) {
    345 
    346       // non blocking read of the next available message
    347       dbus_connection_read_write(conn, 0);
    348       msg = dbus_connection_pop_message(conn);
    349 
    350       // loop again if we haven't read a message
    351       if (NULL == msg) {
    352          sleep(1);
    353          continue;
    354       }
    355 
    356       // check if the message is a signal from the correct interface and with the correct name
    357       if (dbus_message_is_signal(msg, "test.signal.Type", "Test")) {
    358         
    359          // read the parameters
    360          if (!dbus_message_iter_init(msg, &args))
    361             fprintf(stderr, "Message Has No Parameters\n");
    362          else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
    363             fprintf(stderr, "Argument is not string!\n");
    364          else
    365             dbus_message_iter_get_basic(&args, &sigvalue);
    366         
    367          printf("Got Signal with value %s\n", sigvalue);
    368       }
    369 
    370       // free the message
    371       dbus_message_unref(msg);
    372    }
    373 }
    374 
    375 
    376 
    377 int main(int argc, char** argv)
    378 {
    379    if (2 > argc) {
    380       printf ("Syntax: dbus-example [send|receive|listen|query] [<param>]\n");
    381       return 1;
    382    }
    383    char* param = "no param";
    384    if (3 >= argc && NULL != argv[2]) param = argv[2];
    385    if (0 == strcmp(argv[1], "send"))
    386       sendsignal(param);
    387    else if (0 == strcmp(argv[1], "receive"))
    388       receive();
    389    else if (0 == strcmp(argv[1], "listen"))
    390       listen();
    391    else if (0 == strcmp(argv[1], "query"))
    392       query(param);
    393    else {
    394       printf ("Syntax: dbus-example [send|receive|listen|query] [<param>]\n");
    395       return 1;
    396    }
    397    return 0;
    398 } 

    gcc编译问题:

    错误1:
    $ gcc test.c
    test.c:8:23: 错误: dbus/dbus.h:No such file or directory
    ......
    $
    错误提示,dbus库的头文件位置不正确(如果已经安装了dbus的话)
    $ sudo updatedb
    $ sudo locate dbus.h (查看dbus.h的所在位置)
    /usr/local/include/dbus-1.0/dbus/dbus.h
    /usr/include/dbus-1.0/dbus/dbus.h
    看来dbus.h的存放位置的确不正确,这可能是由于dbus-1.0的安装位置有问题,没关系,调整一下dbus的头文件位置就可以了(调整方法如下):
    root@zxl:/usr/include# ln -sf dbus-1.0/dbus
    
    
    错误2:
    $ gcc test.c
    在包含自 test.c:8 的文件中:
    /usr/include/dbus/dbus.h:29:33: 错误: dbus/dbus-arch-deps.h:No such file or directory
    ......
    
    依然有头文件无法正确定位的问题,从错误提示来看,该文件应该在/usr/include/dbus/目录下,可是进入该目录查看竟然没有,那就在整个系统中查找该文件。
    root@zxl:/usr/include/dbus# locate dbus-arch-deps.h
    /usr/local/lib/dbus-1.0/include/dbus/dbus-arch-deps.h
    /usr/lib/dbus-1.0/include/dbus/dbus-arch-deps.h
    将该文件复制到/usr/include/dbus目录下
    
    
    错误3:
    $ gcc test.c
    ......
    test.c:(.text+0xbb6): undefined reference to `dbus_message_iter_get_basic'
    test.c:(.text+0xbd4): undefined reference to `dbus_message_unref'
    collect2: ld 返回 1
    
    需要连接动态库dbus
    $ cd /usr/lib
    $ ls *dbus*
    libdbus-1.a   libdbus-1.so.3      libdbus-glib-1.so
    libdbus-1.la libdbus-1.so.3.2.0 libdbus-glib-1.so.2
    libdbus-1.so libdbus-glib-1.a    libdbus-glib-1.so.2.1.0
    
    $ gcc test.c -l dbus-1 -o dbus

    gcc执行:

    $ ./dbus receive
    Listening for signals
    Match rule sent
    Got Signal with value doctorQBW  
    
    $ ./dbus send doctorQBW    (再开一个标签)
    Sending signal with value doctorQBW
    Signal Sent

    4.2 交叉编译

    交叉编译过程如下:

    将该文件命名dbustest.c

    $ arm-hismall-linux-gcc send.c

    会出现 error:dbus/dbus.h:No such file or directory 即使gcc可以编译而且 dbus/dbus.h就在/usr/include中 也找不到dbus/dbus.h,没办法把bus-1.6.4/dbus目录拷贝到dbustest当前目录,

    将dbustest中的 #include <dbus/dbus.h> 改为 #include "dbus/dbus.h"

    将dbus.h中的 #include <dbus/xxx.h> 都改为 #include "dbus/xxx.h" 

    将bus-1.6.4/dbus/.libs/libdbus-1.so拷贝到 dbustest当前目录

    $ arm-hismall-linux-gcc dbustest.c -o dbustest -I./ -L ./ -ldbus-1

    即可编译通过

    ps:不知道怎么让交叉编译工具通过#include <dbus/xxx.h> 找到/usr/include/dbus下的头文件,若知道请留言指教

    4.3 dbustest测试

    将bus-1.6.4/dbus/.libs/libdbus-1.so.3拷贝到开发板/usr/lib/

    在已经运行dbus-daemon进程的开发板上执行dbustest(命令同gcc测试处)

    可能出现的问题:

    Connection Error (Using X11 for dbus-daemon autolaunch was disabled at compile time, set your DBUS_SESSION_BUS_ADDRESS instead)

    需要设置DBUS_SESSION_BUS_ADDRESS,在执行脚本dbus_run时,会显示

    D-Bus per-session daemon address is: unix:path=/tmp/dbus-pebh4YY2Pp,guid=3ab7577588cdf4e7773663ae38792d8d

     设置环境变量: 

    export DBUS_SESSION_BUS_ADDRESS=‘unix:path=/tmp/dbus-pebh4YY2Pp’

    到此可正常运行dbustest。

     如有错误请指出,如果引用请注明出处: http://www.cnblogs.com/doctorqbw/archive/2012/08/23/2652785.html

  • 相关阅读:
    NLP---word2vec的python实现
    matplotlib---Annotation标注
    matplotlib---legend图例
    matplotlib---设置坐标轴
    windows下右键新建md文件
    vue+webpack+npm 环境内存溢出解决办法
    element-ui tree树形组件自定义实现可展开选择表格
    vue-动态验证码
    ES6 数组函数forEach()、map()、filter()、find()、every()、some()、reduce()
    eslint配置文件规则
  • 原文地址:https://www.cnblogs.com/doctorqbw/p/2652785.html
Copyright © 2020-2023  润新知