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, ¶m)) { 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, ¶m); 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