1、移植dbus到开发板的步骤
先移植dbus-daemon后台进程所依赖的xml解析器:
tar xjf expat-2.3.0.tar.bz2
cd expat-2.3.0
./configure --prefix=$PWD/tmp --host=arm-linux-gnueabihf
make
make install
cp -rfd tmp/* ~/net/nfs_root/fs/usr/
rm -rf ~/net/nfs_root/fs/usr/include/
编译dbus:
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$PWD/expat-2.3.0/tmp/lib/pkgconfig
tar xzf dbus-1.12.20.tar.gz
cd dbus-1.12.20/
./configure --prefix=/usr --host=arm-linux-gnueabihf --disable-tests
make
make install DESTDIR=$PWD/tmp
cp -rfd tmp/usr/* ~/net/nfs_root/fs/usr/
rm -rf ~/net/nfs_root/fs/usr/include/
注意,这里的“–prefix=/usr”并非写错,它与“make install DESTDIR=$PWD/tmp”搭配使用,因为如果类似于expat的配置和编译方式,会导致编译出来的dbus程序和配置文件默认包含了编译主机的路径,这个问题不知道是我没有配置正确还是dbus官方源码中本身存在的一个小bug,所以这里故意将“–prefix”参数来“冒充”成安装到系统目录下,使用以上这种方法就能够解决所说的问题,虽然这种方法可能不是特别标准,或者如果有其他的配置方法不妨大家分享一下。
2、dbus概念介绍以及测试例子
- D-Bus Tutorial
- dbus 简单编程(二) - June_Hou.CSDN
- D-Bus学习(一):总体介绍 - 恺风.CSDN
- Linux进程间通信:D-Bus的使用 - iamlinrm.CSDN (整合csdn作者“恺风”的文章,包含signal和method的收发示例)
编译测试程序的Makefile可以参考:
TARGET := signal_send signal_recieve method_send method_recieve
CC := arm-linux-gnueabihf-gcc
CFLAGS := `pkg-config --cflags dbus-1`
LDFLAGS := `pkg-config --libs dbus-1`
all: $(TARGET)
signal_send: signal_send.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
signal_recieve: signal_recieve.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
method_send: method_send.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
method_recieve: method_recieve.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
clean:
rm -rf $(TARGET)
.PHONY:clean
3、守护进程dbus-daemon的使用
- D-Bus daemon的启动 - szonebit.CSDN (通过dbus-launch来启动dbus-daemon)
- DBus daemon 启动(三) - June_Hou.CSDN(dbus-daemon的多种启动方法)
首先注意到的一点就是,不管dbus-launch还是dbus-daemon程序来启动后台守护进程,都需要系统具备“/dev/null”设备节点,在本次dbus移植测试中就发现buildroot中没有,不过没关系,可以通过mknod /dev/null c 1 3
命令来手动创建,创建完成后重启即可正常使用。
3.1 启动方法
dbus-launch启动
eval `dbus-launch --auto-syntax`
如果只是执行dbus-launch --auto-syntax
命令就可以看到以下输出:
[root@imx6ull]:/work/test
DBUS_SESSION_BUS_ADDRESS='unix:abstract=/tmp/dbusj6FG04pamz,guid=dd172e8d91ca8a769ae7f10a00003fb2';
export DBUS_SESSION_BUS_ADDRESS;
DBUS_SESSION_BUS_PID=150;
[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使用示例:
dbus-daemon --session --print-address --nofork --print-pid
dbus-daemon --session --print-address --fork --print-pid
dbus-daemon --session --print-address --fork --print-pid --introspect
dbus-daemon --session --print-address --fork --print-pid --address=unix:abstract=/tmp/dbus-123456
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的使用
- shell下dbus-send命令小记 - FoxBryant.CSDN
- 用dbus-send查看当前system bus或者session bus上面挂载了多少service - testhw.CSDN
命令使用格式:
dbus-send [–system | —session] [–type=method_call | signal] [–print-reply] [–reply-timeout=超时ms] [–dest=连接名] 对象路径 接口名.方法名 [参数类型:参数值 参数类型:参数值]
示例:
查看system bus上面挂载的service:
dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListActivatableNames
查看session bus上面挂载的service:
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导出它的地址才算使用这个总线),在这个总线上发送消息,就会发现在前面总线的接收程序并没有任何反应。