1、移植dbus到开发板的步骤

先移植dbus-daemon后台进程所依赖的xml解析器:

  1. tar xjf expat-2.3.0.tar.bz2
  2. cd expat-2.3.0
  3. ./configure --prefix=$PWD/tmp --host=arm-linux-gnueabihf
  4. make
  5. make install
  6. cp -rfd tmp/* ~/net/nfs_root/fs/usr/
  7. rm -rf ~/net/nfs_root/fs/usr/include/

编译dbus:

  1. export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$PWD/expat-2.3.0/tmp/lib/pkgconfig
  2. tar xzf dbus-1.12.20.tar.gz
  3. cd dbus-1.12.20/
  4. ./configure --prefix=/usr --host=arm-linux-gnueabihf --disable-tests
  5. make
  6. make install DESTDIR=$PWD/tmp
  7. cp -rfd tmp/usr/* ~/net/nfs_root/fs/usr/
  8. rm -rf ~/net/nfs_root/fs/usr/include/

注意,这里的“–prefix=/usr”并非写错,它与“make install DESTDIR=$PWD/tmp”搭配使用,因为如果类似于expat的配置和编译方式,会导致编译出来的dbus程序和配置文件默认包含了编译主机的路径,这个问题不知道是我没有配置正确还是dbus官方源码中本身存在的一个小bug,所以这里故意将“–prefix”参数来“冒充”成安装到系统目录下,使用以上这种方法就能够解决所说的问题,虽然这种方法可能不是特别标准,或者如果有其他的配置方法不妨大家分享一下。

2、dbus概念介绍以及测试例子

编译测试程序的Makefile可以参考:

  1. TARGET := signal_send signal_recieve method_send method_recieve
  2. CC := arm-linux-gnueabihf-gcc
  3. CFLAGS := `pkg-config --cflags dbus-1`
  4. LDFLAGS := `pkg-config --libs dbus-1`
  5. all: $(TARGET)
  6. signal_send: signal_send.c
  7. $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
  8. signal_recieve: signal_recieve.c
  9. $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
  10. method_send: method_send.c
  11. $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
  12. method_recieve: method_recieve.c
  13. $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
  14. clean:
  15. rm -rf $(TARGET)
  16. .PHONY:clean

3、守护进程dbus-daemon的使用

首先注意到的一点就是,不管dbus-launch还是dbus-daemon程序来启动后台守护进程,都需要系统具备“/dev/null”设备节点,在本次dbus移植测试中就发现buildroot中没有,不过没关系,可以通过mknod /dev/null c 1 3命令来手动创建,创建完成后重启即可正常使用。

3.1 启动方法

dbus-launch启动

  1. eval `dbus-launch --auto-syntax`

如果只是执行dbus-launch --auto-syntax命令就可以看到以下输出:

  1. [root@imx6ull]:/work/test
  2. DBUS_SESSION_BUS_ADDRESS='unix:abstract=/tmp/dbusj6FG04pamz,guid=dd172e8d91ca8a769ae7f10a00003fb2';
  3. export DBUS_SESSION_BUS_ADDRESS;
  4. DBUS_SESSION_BUS_PID=150;
  5. [root@imx6ull]:/work/test

所以加上eval这个命令,在启动dbus-daemon的同时,也设置并且导出了环境变量DBUS_SESSION_BUS_ADDRESS

dbus-daemon启动

先了解参数:

  • –session/–system:bus的类型;
  • –config-file=FILE:使用指定的配置文件;
  • –fork:后台运行,成为daemon进程;
  • –nofork:前台运行;
  • –print-address[=DESCRIPTOR]:打印dbus daemon监听的地址;
  • –print-pid[=DESCRIPTOR]:打印dbus daemon的pid;
  • –introspect:打印内部实现;
  • –address:设置监听地址;
  • –nopidfile:不写pid到文件;
  • –systemd-activation:不知道,没用过;
  • –syslog:记录log和输出到stdout;
  • –syslog-only:只记录log;
  • –nosyslog:只输出stdout。

dbus-daemon使用示例:

  1. dbus-daemon --session --print-address --nofork --print-pid
  2. dbus-daemon --session --print-address --fork --print-pid
  3. dbus-daemon --session --print-address --fork --print-pid --introspect
  4. dbus-daemon --session --print-address --fork --print-pid --address=unix:abstract=/tmp/dbus-123456
  5. export DBUS_SESSION_BUS_ADDRESS='unix:abstract=...'

3.2 配置文件

看到一些文章,以session为例,好像都是讲dbus-daemon后台守护进程会使用到/usr/etc/dbus-1/session.conf这个配置文件(/etc还是/usr/etc目录得看移植时的配置),但是我找到这个文件打开一看,里面并没有什么配置的内容,只是提及了老版本会使用到这个配置文件,新版本(我使用的是dbus-1.12.20版本)使用的是/usr/share/dbus-1/session.conf,这个文件,让我们不用改。如果需要配置的话,也可以在同目录下创建文件session-local.conf,或者在session.d/目录下创建.conf格式的文件,这些文件已经被session.conf的busconfig元素包含进去了,并且它们会覆盖原有的配置。

4、dbus-send的使用

命令使用格式:

dbus-send [–system | —session] [–type=method_call | signal] [–print-reply] [–reply-timeout=超时ms] [–dest=连接名] 对象路径 接口名.方法名 [参数类型:参数值 参数类型:参数值]

示例:

查看system bus上面挂载的service:

  1. dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListActivatableNames

查看session bus上面挂载的service:

  1. dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListActivatableNames

5、其他问题

Q1:如果存在多个session总线,那么应用程序连接时会使用到哪个总线?

A1:dbus_bus_get函数为例,应用程序调用该函数连接总线时,是通过获取环境变量DBUS_SESSION_BUS_ADDRESS来找到与某个总线通信的地址,所以即使启动了多个总线,但终究还是根据该环境变量来找到对应的那条总线进行通信。

Q2:不同session总线间的应用程序能相互通信吗?

A2: 不能,这点可以简单地验证。先启动一个总线之后,后台运行一个用于接收消息的应用程序,然后再另外启动一个总线(记得也要export导出它的地址才算使用这个总线),在这个总线上发送消息,就会发现在前面总线的接收程序并没有任何反应。