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

posted on 2012-08-23 17:10  千兵卫博士  阅读(6139)  评论(0编辑  收藏  举报

导航