Tag Archives: dbus

什么是D-Bus?

有朋友在鸟嘀咕上要求我解释一下,我觉得简单来讲是解释不清楚的,所以打算写篇blog回复。 从功能上来说,它提供了程序之间互相交互的一个简单接口,程序可以尽量不关心关于底层的通信细节,而方便地和其他程序进行通信。它不仅仅在Linux和UNIX上实现了,同时也有Windows的移植版本(KDE4的Windows版就有用到)。 它对于底层的通信协议进行了封装,提供了相应的基本数据类型,简化了对于序列化的繁复操作,开发者只需要关心对应的操作即可。 从基础概念来说,一个程序会注册至少一个Service,这个service可以是一个公共的名称(这样的话就是一个面向开放的Service,期待其他人主动调用。)这个名称可以设置为互斥的,或者是可以无缝地由其他程序进行接管。或者不使用一个公共的名称,这样一般就是作为一个client。 每个Service下面有多个Object,每个Object可能实现多个interface,interface里面定义的是这个Object的属性(property),方法(method),或者信号(signal)。通过一个xml文件定义。对于一个object来说,它有义务实现org.desktop.DBus.Introspectable接口,别的dbus程序就可以通过调用这个接口的Introspect方法询问你对于接口的支持情况。 dbus里面的方法就像是一般的ipc/rpc调用一样,有参数,返回值。可以call给某个service的某个object的某个method。这一般可以用于dbus内的client和逻辑上的server进行通信(因为实际上dbus是使用一个daemon的形式运行,中间由他进行转发)。signal的概念可以认为是一种广播的机制,其他的dbus service可以选择按照某个filter监听signal,在signal触发的时候进行对应的处理。property则有它对应的get,set,以及在改变的时候触发标准的org.freedesktop.DBus.Properties.PropertiesChanged signal。 对于Glib,Qt,Python等等库,都有对dbus按照它进行抽象和封装,例如对于Qt来说,就可以将method和slot联系起来,signal和qt的signal联系起来,object就可以作为一个实际的“QObject”。通过qdbusxml2cpp这个命令生成对应的c++代码。 dbus上也提供了非常多的工具进行调试或者是命令访问,例如可以通过dbus-moniter监控某个channel上的dbus通信,或者直接使用dbus-send发送dbus的消息。qdbusviewer则是提供了一个可视化的界面,可以查看session和system两个channel的dbus操作。 dbus本身也是一个依赖非常轻量的库,除了一个xmlparser之外,就只有对应平台上的一些库。 如果想要通过dbus的底层api实现一个dbus程序(比如fcitx这样的),一般而言有两种简单的方法。 一个是在获得可用的dbus_connection之后,通过dbus_connection_read_write 直接一条条地处理dbus message(前面的method,signal其实都是一种dbus message),或者实现一个main loop,并且通过dbus_connection_set_watch_functions 注册一些函数,用来监视实际的dbus操作的fd,然后或者通过select,或者使用libevent,libev,在确认有dbus的消息到来后调用 dbus_watch_handle 和 dbus_connection_dispatch 处理消息。(实际上glib等库中就是这样实现的) D-Bus 本身大大简化了不同程序之间通信的开发,并且稳定性也已经接受了多年的检验,对于开发一个需要通信桌面程序来说是一个很好的选择,并且也已经有无数程序选择了dbus作为它开放的接口,比如媒体播放器就有mpris接口来监控或者操作播发器的状态。

Posted in Linux | Tagged | 5 Comments

valgrind的调试fcitx的记录

今天调fcitx和kimpanel,以前杯具的sigpipe再度出现,幸好不使用dbus时不会出现这个问题,要不我还不被骂死…… 上网查了查dbus的sigpipe,信息不多,感觉一头雾水无从选择……相关的一个信息就是dbus的多线程问题,需要用dbus_threads_init_default,这个问题在当年决定用另外的线程来接收dbus信息时就用上了,所以导致我更加百思不得其解…… 幸好这个问题不甚多见,我能reproduce的情况就是,打开拼音,按left ctrl进英文模式,按shift+space切换全半角,然后就sigpipe。甚是杯具。我猜很多人也不这么用,甚至全角都完全不用,所以有幸躲过了。 回到这个问题上来,今天不断的测试之后还是没有解决,倒是有的时候segfault了。赶快看一看,发现问题总是出在property2string这个函数上面,很奇怪,于是祭出valgrind大神救我。 valgrind大神真是好,当年fcitx的dbus功能内存泄露大大滴……用了这个,真是腰不酸了,背不疼了,走路也有劲了,顺道还查出了个fcitx原来隐藏的内存泄露问题。 单纯记录经历就没啥意思了,也说说怎么用上它的,基本上这个命令总是这么敲就好了: valgrind –trace-children=yes –leak-check=full –log-file=filename commands args 其中第一个参数是记录子进程,第二个是显示完整的内存泄露信息,第三个是制定记录输出的文件,默认是重定向到stderr的。 于是乎,果然让我发现了一个问题,是新写的函数updatePropertyByConnectID有个问题,logo_prop这个变量记录了kimpanel第一个图标的信息,这里我在赋值之后将它free掉了……也许就是这个原因导致的,不过再我改过来之前就被亲爱的打发走了…… 回去之后看看是否能解决这个问题。 余下的是杂谈: 话说回来,我还是需要吐吐嘈,dbus实际上大家都在用dbus和glib的绑定(或者qt),这也无可厚非,但是我实在不想为fcitx加入新的依赖,dbus毕竟还是人人都安装的嘛。(什么,你不装dbus,主流桌面你还想用吗,你真的用linux做桌面吗)所以一直只用了dbus的核心部分,结果就没有办法做一个好的事件处理,这让人很苦恼。另外由于开了多线程,幸好有个dbus有个加锁的功能所以才能解决。fcitx确实很轻量级,带来的问题就是可扩展性上的缺失,这也算是一个feature吧……不用kimpanel的人大可以放心不用重新编译,在配置文件里面写上使用dbus接口=0就好,而且默认是不用的,不会带来啥性能和崩溃问题(基本确定,我check过屏蔽的还是很好的)。 用dbus底层接口带来的问题就是得自己搞个轮询……试了试sleep起码没有带来啥性能问题,就暂且放过。 fcitx的界面逻辑和核心逻辑混杂在一起,所以带来了很多问题……但是拆开来难得要做第二个ibus不成吗?……而且恐怕工程量巨大,也没有啥精力去搞这个了…… 其实说起来我还给fcitx搞过整体的utf8化哦……当时倒是有初步结果,只不过最后无疾而终了…… 说起来我为什么一直执着于fcitx,很多人也执着于fcitx呢?其实我执着的原因还蛮简单的,就是兼容性啊,纯底层x写的输入法,没有gtk,qt的依赖,真是很好的输入法。大多数人可能看重的是轻量吧。 fcitx的拼音输入其实还不错,只不过默认的词库小了点,具体的处理也是hand made的。有时候总会觉得有点遗憾,用了附加词库当然好了很多,不过貌似是最近匹配的算法?有时候输入有点小问题。 如果有人port一个新输入法算法过来可能会好很多。其实fcitx有很多人性化的地方,删除用户词库,record,等等都很方便。 不知道yuking对于小企鹅输入法的将来怎么看,活跃着的开发者貌似只有yuking?…… 不知道联系一下学校的协会怎么样

Posted in fcitx development | Tagged , , , , | Leave a comment