dbus 初探 版本 dbus-1.4.0

来源:互联网 发布:女程序员容易老吗 编辑:程序博客网 时间:2024/05/21 05:23

      dbus 初探 版本 dbus-1.4.0

转载时请注明出处和作者联系方式
文章出处:http://www.lt-net.cn
作者联系方式:刘敏  <qtgirl666@gmail.com>

编译系统Ubuntu10.04(确保/opt 可写)交叉编译器arm-linux-gcc 4.3.3硬件设备LT2440开发板  测试软件dbus-1.4.0依赖库libxml2-2.7.6

   一直以来都想学习dbus,想把dbus移植到LT2440开发板上,今天弱弱的看了一下相关的资料,编译了dbus库,并且做了一个测试。
   首先,编译 libxml2-2.7.6
$ ./configure --host=arm-linux --prefix=/opt/gtkfb
$ make
$ make install
   其次,编译dbus-1.4.0
需要先让dbus找到 libxml 库,使用PKG_CONFIG_PATH,使用下面的export 命令即可
$ export PKG_CONFIG_PATH=/opt/gtkfb/lib/pkgconfig
$ ./configure --host=arm-linux --prefix=/opt/gtkfb --without-x --with-xml=libxml
$ make
$ make install
这样dbus库就编译好了,并且会得到一些命令,在/opt/gtkfb/bin目录下,以dbus开头
将相关库拷贝到文件系统,拷贝以上命令到bin目录,已经移植好了,找一个程序做测试
sample.c

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

makefile

  1. CC     = arm-linux-gcc
  2. CFLAGS += -Wall -g -I/opt/gtkfb/include/dbus-1.0 -I/opt/gtkfb/lib/dbus-1.0/include
  3. LIBS   += -Wall -g -L/opt/gtkfb/lib -ldbus-1 -lpthread -lrt
  4. TARGET  = sample
  5. OBJ    = $(TARGET).o
  6. all: $(TARGET)
  7. %o: %c
  8. $(CC) $(CFLAGS) -c $< -o $@
  9. $(TARGET): $(OBJ)
  10. $(CC) $(LIBS) -o $(TARGET) $(OBJ)
复制代码

编译后得到 sample 可执行文件,放入开发板文件系统
执行,出现如下错误,查看资料得知,需要先配置dbus才可以使用它
作如下的配置:
1.先运行dbus-daemon
$ dbus-daemon –system –print-pid –print-address
出现如下错误:Failed to start message bus: Could not get UID and GID for username “messagebus”
添加一个用户就可  
$ adduser  messagebus
2.再执行sample 出现如下错误
D-Bus library appears to be incorrectly set up; failed to read machine uuid: Failed to open “/opt/gtkfb/lib/dbus/machine-id”: No such file or directory
缺少machine-id ,dbus 提供dbus-uuidgen命令产生machine-id
$ dbus-uuidgen >  /opt/gtkfb/lib/dbus/machine-id
3.再执行sample 出现如下错误
Connection Error (/opt/gtkfb/bin/dbus-launch terminated abnormally with the foll
owing error: Autolaunch requested, but X11 support not compiled in.
这个需要先获得DBUS_SESSION_BUS_ADDRESS,使用 dbus-launch命令
$ dbus-launch
DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/dbus-7dbR7xlNbT,guid=3c7319d183feacf6a4faf8160000029b
DBUS_SESSION_BUS_PID=452

$ export  DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/dbus-7dbR7xlNbT,guid=3c7319d183feacf6a4faf8160000029b
再执行sample就可以启动了

signal运行实例
运行server
$ ./sample receive  &
Listening for signals
Match rule sent

运行client
$ ./sample send  lt2440

Sending signal with value lt2440
Signal Sent
Got Signal with value lt2440


method运行实例
运行server
$ ./sample listen &
Listening for method calls

运行client
$ ./sample query lt2440

Calling remote method with luther.gliethttp.12345678
Request Sent
Method called with lt2440
Got Reply: 0, 21614



dbus在lt2440开发板上成功执行。dbus封装的程序通信比较方便,简单,高效