Vim 居中光标所在行与大小写切换

经常忘记了,记录一下 😉

居中光标所在行
曾经用Emacs的时候发现那个Ctrl-L特别好用,看到光标在下面了按一下就把那行提到屏幕中间来了,于是想在vim中找类似的功能,想想也该有嘛,所以就找到了,而且有三条~

zz: 将当前行置于屏幕中间(不是转载…)
zt: 将当前行置于屏幕顶端(不是猪头~)
zb:底端啦~

还有一条就是移动光标所在行的位置,就是说,比如我光标在第10行,我想光标不动,但是所在行向上移,ctrl-e啦,然后向下的话,ctrl-y~

大小写切换
在vim中,通过v选中的文字可以用u切换到小写,U切换到大写,~在大小写之间切换,但是如果需要对选定的词做大小写操作,就需要用到%s中的\u,\U,\l和\L,\u是把后续的字符串第一个字符转成大写而\U是把后续的都转成大写(upper case),\l和\L是转成小写(lower case)

例如如果要把所有行首的单词首字母大写后面的所有字母都小写,可以这么折腾:

:%s/^\(\w\)\(.*\)/\u\1\L\2/g

需要注意的一点是,如果\L和\U后面跟有别的字符串,也会被弄成大写,如对字符串abcdefg运行 %s/abcd/\Uefgh/g 的结果就是 EFGHefg,这一点在使用反向引用\1, \2等的时候比较麻烦,例如我\1取到的是一个单词,我需要把它们都大写化了,然后后面的\2也会被变成大写。刚好下午试的是给变量改名字,在需要变大写的单词后面有一条下划线,于是就这么用了:

:%s/_\([a-z]\)_\(.*\)/_\U\1\l_\2/g

\l 对下划线没影响,刚好用来抵消 \U 的作用,满好,至于别的情况,暂时没想法……

Over!

From: http://www.hzmangel.info/blog/archives/490 http://www.hzmangel.info/blog/archives/491

SSH using a SOCKS or HTTP proxy

If you follow planet debian, you may already know about the ProxyCommand directive in $HOME/.ssh/config. It allows OpenSSH to connect to a remote host through a given command.

One setup that I use a lot is to have connections be established through a SOCKS proxy. Until today, I was using connect, a small tool written by Shun-ichi Gotô. The typical setup I used is:

    Host *.mydomain.com
    ProxyCommand connect -S socksserver:1080 %h %p

I also use jump hosts occasionally, with a setup like this:

    Host somehost.mydomain.com
    ProxyCommand ssh otherhost.mydomain.com nc -w1 %h %p

And today I discovered that netcat-openbsd does support connexions through a proxy, either SOCKS or HTTP. Why keep using two different tools when you can use one? 😉 So I changed my setup to:

    Host *.mydomain.com
    ProxyCommand nc -xsocksserver:1080 -w1 %h %p

The default is to use SOCKS 5, add -X4 for SOCKS 4 and -Xconnect for HTTP CONNECT proxies. Note that it doesn’t support choosing which end does the name resolutions like connect does with the -R option.

From: http://glandium.org/blog/?p=223

Over!

Sharing Mounts

Occasionally, certain system administration tasks require access to the same file system from more than one place in the directory tree (for example, when preparing a chroot environment). To address such requirements, the mount command implements the –bind option that provides a means for duplicating certain mounts. Its usage is as follows:

mount --bind old_directory new_directory

Although the above command allows a user to access the file system from both places, it does not apply on the file systems that are mounted within the original directory. To include these mounts as well, type:

mount --rbind old_directory new_directory

Additionally, to provide as much flexibility as possible, Red Hat Enterprise Linux 5.8 implements the functionality known as shared subtrees. This feature allows you to use the following four mount types:

Shared Mount
A shared mount allows you to create an exact replica of a given mount point. When a shared mount is created, any mount within the original mount point is reflected in it, and vice versa. To create a shared mount, type the following at a shell prompt:

mount --make-shared mount_point

Alternatively, you can change the mount type for the selected mount point and all mount points under it:

mount --make-rshared mount_point

Example: Creating a Shared Mount Point
There are two places where other file systems are commonly mounted: the /media directory for removable media, and the /mnt directory for temporarily mounted file systems. By using a shared mount, you can make these two directories share the same content. To do so, as root, mark the /media directory as “shared”:

~]# mount --bind /media /media
~]# mount --make-shared /media

Then create its duplicate in /mnt by using the following command:

~]# mount --bind /media /mnt

You can now verify that a mount within /media also appears in /mnt. For example, if you have non-empty media in your CD-ROM drive and the /media/cdrom/ directory exists, run the following commands:

~]# mount /dev/cdrom /media/cdrom
~]# ls /media/cdrom
EFI  GPL  isolinux  LiveOS
~]# ls /mnt/cdrom
EFI  GPL  isolinux  LiveOS

Similarly, you can verify that any file system mounted in the /mnt directory is reflected in /media. For instance, if you have a non-empty USB flash drive that uses the /dev/sdc1 device plugged in and the /mnt/flashdisk/ directory is present, type:

~]# mount /dev/sdc1 /mnt/flashdisk
~]# ls /media/flashdisk
en-US  publican.cfg
~]# ls /mnt/flashdisk
en-US  publican.cfg

Slave Mount
A slave mount allows you to create a limited duplicate of a given mount point. When a slave mount is created, any mount within the original mount point is reflected in it, but no mount within a slave mount is reflected in its original. To create a slave mount, type the following at a shell prompt:

mount --make-slave mount_point

Alternatively, you can change the mount type for the selected mount point and all mount points under it:

mount --make-rslave mount_point

Example: Creating a Slave Mount Point
Imagine you want the content of the /media directory to appear in /mnt as well, but you do not want any mounts in the /mnt directory to be reflected in /media. To do so, as root, first mark the /media directory as “shared”:

~]# mount --bind /media /media
~]# mount --make-shared /media

Then create its duplicate in /mnt, but mark it as “slave”:

~]# mount --bind /media /mnt
~]# mount --make-slave /mnt

You can now verify that a mount within /media also appears in /mnt. For example, if you have non-empty media in your CD-ROM drive and the /media/cdrom/ directory exists, run the following commands:

~]# mount /dev/cdrom /media/cdrom
~]# ls /media/cdrom
EFI  GPL  isolinux  LiveOS
~]# ls /mnt/cdrom
EFI  GPL  isolinux  LiveOS

You can also verify that file systems mounted in the /mnt directory are not reflected in /media. For instance, if you have a non-empty USB flash drive that uses the /dev/sdc1 device plugged in and the /mnt/flashdisk/ directory is present, type:

~]# mount /dev/sdc1 /mnt/flashdisk
~]# ls /media/flashdisk
~]# ls /mnt/flashdisk
en-US  publican.cfg

Private Mount
A private mount allows you to create an ordinary mount. When a private mount is created, no subsequent mounts within the original mount point are reflected in it, and no mount within a private mount is reflected in its original. To create a private mount, type the following at a shell prompt:

mount --make-private mount_point

Alternatively, you can change the mount type for the selected mount point and all mount points under it:

mount --make-rprivate mount_point

Example: Creating a Private Mount Point
Taking into account the scenario in Example 2.4, “Creating a Shared Mount Point”, assume that you have previously created a shared mount point by using the following commands as root:

~]# mount --bind /media /media
~]# mount --make-shared /media
~]# mount --bind /media /mnt

To mark the /mnt directory as “private”, type:

~]# mount --make-private /mnt

You can now verify that none of the mounts within /media appears in /mnt. For example, if you have non-empty media in your CD-ROM drive and the /media/cdrom/ directory exists, run the following commands:

~]# mount /dev/cdrom /media/cdrom
~]# ls /media/cdrom
EFI  GPL  isolinux  LiveOS
~]# ls /mnt/cdrom
~]#

You can also verify that file systems mounted in the /mnt directory are not reflected in /media. For instance, if you have a non-empty USB flash drive that uses the /dev/sdc1 device plugged in and the /mnt/flashdisk/ directory is present, type:

~]# mount /dev/sdc1 /mnt/flashdisk
~]# ls /media/flashdisk
~]# ls /mnt/flashdisk
en-US  publican.cfg

Unbindable Mount
An unbindable mount allows you to prevent a given mount point from being duplicated whatsoever. To create an unbindable mount, type the following at a shell prompt:

mount --make-unbindable mount_point

Alternatively, you can change the mount type for the selected mount point and all mount points under it:

mount --make-runbindable mount_point

Example: Creating an Unbindable Mount Point
To prevent the /media directory from being shared, as root, type the following at a shell prompt:

~]# mount --bind /media /media
~]# mount --make-unbindable /media

This way, any subsequent attempt to make a duplicate of this mount will fail with an error:

~]# mount --bind /media /mnt
mount: wrong fs type, bad option, bad superblock on /media/,
       missing code page or other error
       In some cases useful info is found in syslog - try
       dmesg | tail  or so

From: https://access.redhat.com/knowledge/docs/en-US/Red_Hat_Enterprise_Linux/5/html/Deployment_Guide/sect-Using_the_mount_Command-Mounting-Bind.html

Over!

组播技术中IPv4地址到MAC地址的映射

以太网组播MAC地址

以太网传输单播IP报文的时候,目的MAC地址使用的是接收者的MAC地址。但是在传输组播数据包时,其目的地不再是一个具体的接收者,而是一个成员不确定的组,所以要使用组播MAC地址。

IPv4组播MAC地址
IANA规定,IPv4组播MAC地址的高24位为0x01005E,第25位为0,低23位为IPv4组播地址的低23位。IPv4组播地址与MAC地址的映射关系如图1-6所示。

图1-6 IPv4组播地址与MAC地址的映射关系

由于IPv4组播地址的高4位是1110,代表组播标识,而低28位中只有23位被映射到IPv4组播MAC地址,这样IPv4组播地址中就有5位信息丢失。于是,就有32个IPv4组播地址映射到了同一个IPv4组播MAC地址上,因此在二层处理过程中,设备可能要接收一些本IPv4组播组以外的组播数据,而这些多余的组播数据就需要设备的上层进行过滤了。

Over!

From: http://0bill0.blog.51cto.com/195306/300481

内存屏障是什么?

内存屏障是指“由于编译器的优化和缓存的使用,导致对内存的写入操作不能及时的反应出来,也就是说当完成对内存的写入操作之后,读取出来的可能是旧的内容”

内存屏障的分类
1. 编译器引起的内存屏障
2. 缓存引起的内存屏障
3. 乱序执行引起的内存屏障

编译器引起的内存屏障
我们都知道,从寄存器里面取一个数要比从内存中取快的多,所以有时候编译器为了编译出优化度更高的程序,就会把一些常用变量放到寄存器中,下次使用该变量的时候就直接从寄存器中取,而不再访问内存,这就出现了问题,当其他线程把内存中的值改变了怎么办?也许你会想,编译器怎么会那么笨,犯这种低级错误呢!是的,编译器没你想象的那么聪明!让我们看下面的代码:(代码摘自《独辟蹊径品内核》)

int flag=0;
 
void wait(){
    while ( flag == 0 )
        sleep(1000);
    ......
}
 
void wakeup(){
    flag=1;
}

这段代码表示一个线程在循环等待另一个线程修改flag。 Gcc等编译器在编译的时候发现,sleep()不会修改flag的值,所以,为了提高效率,它就会把某个寄存器分配给flag,于是编译后就生成了这样的伪汇编代码:

void wait(){
    movl  flag, %eax;
 
    while ( %eax == 0)
        sleep(1000);
}

这时,当wakeup函数修改了flag的值,wait函数还在傻乎乎的读寄存器的值而不知道其实flag已经改变了,线程就会死循环下去。由此可见,编译器的优化带来了相反的效果!

但是,你又不能说是让编译器放弃这种优化,因为在很多场合下,这种优化带来的性能是十分可观的!那我们该怎么办呢?有没有什么办法可以避免这种情况?答案必须是肯定的,我们可以使用关键字volatile来避免这种情况。

volatile int flag = 0;

这样,我们就能避免编译器把某个寄存器分配给flag了。

好,上面所描述这些,就叫做“编译器优化引起的内存屏障”,是不是懂了点什么?再回去看看概念?

缓存引起的内存屏障
好,既然寄存器能够引起这样的问题,那么缓存呢?我们都知道,CPU会把数据取到一个叫做cache的地方,然后下次取的时候直接访问cache,写入的时候,也先将值写入cache。

那么,先让我们考虑,在单核的情况下会不会出现问题呢?先想一下,单核情况下,除了CPU还会有什么会修改内存?对了,是外部设备的DMA!那么,DMA修改内存,会不会引起内存屏障的问题呢?答案是,在现在的体系结构中,不会。

当外部设备的DMA操作结束的时候,会有一种机制保证CPU知道他对应的缓存行已经失效了;而当CPU发动DMA操作时,在想外部设备发送启动命令前,需要把对应cache中的内容写回内存。在大多数RISC的架构中,这种机制是通过一写个特殊指令来实现的。在X86上,采用一种叫做总线监测技术的方法来实现。就是CPU和外部设备访问内存的时候都需要经过总线的仲裁,有一个专门的硬件模块用于记录cache中的内存区域,当外部设备对内存写入的时候,就通过这个硬件来判断下改内存区域是否在cache中,然后再进行相应的操作。

那么,什么时候才能产生cache引起的内存屏障呢?多CPU? 是的,在多CPU的系统里面,每个CPU都有自己的cache,当同一个内存区域同时存在于两个CPU的cache中时,CPU1改变了自己cache中的值,但是CPU2却仍然在自己的cache中读取那个旧值,这种结果是不是很杯具呢?因为没有访存操作,总线也是没有办法监测的,这时候怎么办?

对阿,怎么办呢?我们需要在CPU2读取操作之前使自己的cache失效,x86下,很多指令能做到这点,如lock前缀的指令,cpuid, iret等。内核中使用了一些函数来完成这个功能:mb(), rmb(), wmb()。用的也是以上那些指令,感兴趣可以去看下内核代码。

乱序执行引起的内存屏障
我们都知道,超标量处理器越来越流行,连龙芯都是四发射的。超标量实际上就是一个CPU拥有多条独立的流水线,一次可以发射多条指令,因此,很多允许指令的乱序执行,具体怎么个乱序方法,可以去看体系结构方面的书,这里只说内存屏障。

指令乱序执行了,就会出现问题,假设指令1给某个内存赋值,指令2从该内存取值用来运算。如果他们两个颠倒了,指令2先从内存中取值运算,是不是就错了?

对于这种情况,x86上专门提供了lfence,sfence,和mfence 指令来停止流水线:
lfence:停止相关流水线,知道lfence之前对内存进行的读取操作指令全部完成
sfence:停止相关流水线,知道lfence之前对内存进行的写入操作指令全部完成
mfence:停止相关流水线,知道lfence之前对内存进行的读写操作指令全部完成

好,将完这三种类型,再回去看看概念,清晰了么?如果还不明白,那就是我的表达能力太有限了,自己网上再搜搜把!

From: http://www.spongeliu.com/%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0/clanguage/memorybarrier/

Over!

Systemd socket activation and Ruby

For anyone who doesn’t know what systemd is:

systemd is a system and service manager for Linux, compatible with SysV and LSB init scripts. systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux cgroups, supports snapshotting and restoring of the system state, maintains mount and automount points and implements an elaborate transactional dependency-based service control logic.

http://www.freedesktop.org/wiki/Software/systemd

It’s quite similar to Apple’s launchd (used in OSX) and is fully utilizing powerful features of the latest Linux kernel. systemd is default init system in latest Fedora, openSUSE and Mandriva and is available for many other Linux distros as alternative boot solution. I hope Ubuntu’s upstart team will give up soon because having systemd on Ubuntu servers would be awesome. For more info and idea behind the project I recommend reading Lennart Poettering’s announcement

One of the great features of this init system is socket activation of system services. In short, services are lazily started when they’re actually needed. Systemd listens on the sockets for them and starts the services on first incoming connection, passing them the listening sockets. Started services just start accepting clients on these sockets (without calling socket()+bind()+listen()).

It appears that the protocol for passing sockets to service processes is very simple. Environment variable LISTEN_PID is set to the PID of the service process and another environment variable LISTEN_FDS is set to the number of listening sockets passed. Socket descriptors start from number 3 and are sequential. For example, LISTEN_FDS with value of 2 means process should accept connections on 2 sockets with descriptors 3 and 4.

I’ll show you how all this works on an example echo server written in ruby. The server will send back what it receives. Additionally it will send information telling if listening socket came from systemd or not to each new connected client.

But first we need to create the socket unit file that specifies where systemd should listen on behalf of our service. /etc/systemd/system/echo-server.socket file can look as simple as this:

[Socket]
ListenStream=8888

Next, we need service unit file that specifies what binary to start when connections start coming. /etc/systemd/system/echo-server.service file may look like this:

[Service]
ExecStart=/home/kill/.rvm/bin/ruby-1.9.2-p290 /home/kill/bin/echo-server.rb
User=kill
StandardOutput=syslog
StandardError=syslog

I have ruby 1.9.2 installed via RVM so I’m running my ruby script with RVM’s wrapper specifying full paths (remember init process runs as root). I’m also setting the user on whose behalf the process should be run and I’m asking systemd to log process’ stdout/stderr to syslog (simplifies debugging).

Now, the echo server (/home/kill/bin/echo-server.rb):

#!/usr/bin/env ruby
 
require 'socket'
 
SD_LISTEN_FDS_START = 3
 
from_systemd = false
 
if ENV['LISTEN_PID'].to_i == $$
  # use existing socket passed from systemd
  server_socket = Socket.for_fd(SD_LISTEN_FDS_START + 0)
  from_systemd = true
else
  # create new listening socket on port 8888
  server_socket = Socket.tcp_server_sockets(8888)
end
 
Socket.accept_loop(server_socket) do |client_socket, addr|
  client_socket.send("OHAI! systemd socket: #{from_systemd}\n", 0)
 
  while (data = client_socket.recv(1000)).size > 0
    client_socket.send(data.upcase, 0)
  end
end

Implementation is very simple, still I’m gonna explain it a little bit as it illustrates the use of systemd socket activation protocol and the fallback – normal way of creating server socket.

Like I mentioned earlier, descriptors of systemd passed sockets start with 3:

SD_LISTEN_FDS_START = 3

We check if LISTEN_PID points to our echo-server.rb process:

if ENV['LISTEN_PID'].to_i == $$

If so, we’re creating new Socket instance for existing descriptor (3). Socket unit file tells systemd to listen on one port only (8888) so we can assume there’s only one socket descriptor passed:

  # use existing socket passed from systemd
  server_socket = Socket.for_fd(SD_LISTEN_FDS_START + 0)

If LISTEN_PID doesn’t match our process we just create TCP socket the usual way:

else
  # create new listening socket on port 8888
  server_socket = Socket.tcp_server_sockets(8888)
end

Finally, in Socket.accept_loop(server_socket) do { … } we handle incoming clients.

From: http://ku1ik.com/2012/01/21/systemd-socket-activation-and-ruby.html

Over!

Gedit 3 Plugin Sample

Required bindings not yet included in vala:
Gedit >= 3.0 (gedit-3.0.vapi)
GtkSource View >= 3.0 (gtksourceview-3.0.vapi)
PeasGtk-1.0 gobject introspection package of your distro
…and Vala >= 0.11

Source & support files
A Gedit plugin is composed of just two files: a library (.so) and the plugin file definition.

Our example plugin will be contained in just one vala soure file, so with all the dependencies in place this should be the directory listing:

$ ls
gedit-3-example.plugin
gedit-3-example-plugin.vala
gedit-3.0.vapi
gtksourceview-3.0.vapi

In order to make the example really simple we decided to implement a very basic function: the plugin will just close an xml tag upon writing the ‘>’. Eg. if you write it will add the corresponding close tag.

Source code for the file: gedit-3-example-plugin.vala

using GLib;
 
namespace GeditPluginExample
{
        /*
         * This class will be instantiated and activated for each Gedit View
         */
        public class View : Gedit.ViewActivatable, Peas.ExtensionBase
        {
                public View ()
                {
                        GLib.Object ();
                }
 
                public Gedit.View view {
                         get; construct;
                }
 
                public void activate ()
                {
                        print ("View: activated\n");
                        view.key_release_event.connect (this.on_key_release);
                }
 
                public void deactivate ()
                {
                        print ("View: deactivated\n");
                        view.key_release_event.disconnect (this.on_key_release);
                }
 
                private bool on_key_release (Gtk.Widget sender, Gdk.EventKey event)
                {
                        if (event.str == ">") {
                                // Close the tag
                                Gedit.View view = (Gedit.View)sender;
                                Gtk.TextBuffer buffer = view.get_buffer ();
                                Gtk.TextIter end, start;
 
                                buffer.get_iter_at_mark (out end, (Gtk.TextMark) buffer.get_insert ());
                                if (end.backward_char ()) {
                                        start = end;
                                        if (start.backward_word_start ()) {
                                                string tag = "</%s>".printf (buffer.get_text (start, end, false));
 
                                                // add the closing tag
                                                buffer.begin_user_action ();
                                                buffer.insert_interactive_at_cursor (tag, -1, true);
                                                buffer.end_user_action ();
 
                                                // move cursor back
                                                buffer.get_iter_at_mark (out end, (Gtk.TextMark) buffer.get_insert ());
                                                end.backward_chars (tag.length);
                                                buffer.place_cursor (end);
                                        }
                                }
                        }
                        return true;
                }
        }
 
        /*
         * Plugin config dialog
         */
        public class Config : Peas.ExtensionBase, PeasGtk.Configurable
        {
                public Config () 
                {
                        Object ();
                }
 
                public Gtk.Widget create_configure_widget () 
                {
                        return new Gtk.Label (" Gedit 3.0 Example Vala Plugin ");
                }
        }
}
 
[ModuleInit]
public void peas_register_types (TypeModule module) 
{
        var objmodule = module as Peas.ObjectModule;
 
        // Register my plugin extension
        objmodule.register_extension_type (typeof (Gedit.ViewActivatable), typeof (GeditPluginExample.View));
        // Register my config dialog
        objmodule.register_extension_type (typeof (PeasGtk.Configurable), typeof (GeditPluginExample.Config));
}

Contents of the plugin definition file: gedit-3-example.plugin

[Plugin]
Module=gedit-3-example-plugin.so
IAge=2
Name=Vala Example Plugin
Description=A simple Vala Example Plugin
Authors=Andrea Del Signore <sejerpz@tin.it>
Copyright=Copyright © 2011 Andrea Del Signore
Website=http://live.gnome.org/action/Vala/Gedit3PluginSample

Compiling & Installing

$ valac --vapidir . -C gedit-3-example-plugin.vala --pkg gtk+-3.0 --pkg gedit-3.0 --pkg PeasGtk-1.0 --pkg GtkSource-3.0
$ gcc --shared -o libgedit-3-example-plugin.so gedit-3-example-plugin.c `pkg-config --cflags --libs gedit gtk+-3.0 gtksourceview-3.0 libpeas-gtk-1.0`
$ cp libgedit-3-example-plugin.so gedit-3-example.plugin ~/.local/share/gedit/plugins/

Running
Start GEdit 3 and enable the plugin from the edit -> preference menu

Over!

From: https://live.gnome.org/Vala/Gedit3PluginSample

Having pacman verify packages

For the past six months, pacman’s package verification features were turned off by default while we were figuring out the details of our public-key infrastructure.

They have finally been enabled in pacman-4.0.3-2; when you upgrade, you will be prompted to run:

pacman-key --init
pacman-key --populate archlinux

This sets up a local keyring for pacman, and populates it with the data needed to authenticate official packages. This includes five master keys used to authenticate Arch Linux packagers (developers and trusted users), so you do not need to know who joins or leaves the team: you only have to verify those five master keys once and for all. The populate command will prompt you to do so; please do this cautiously by checking the fingerprints displayed against those published on our website.

Then, merge your pacman.conf with pacman.conf.pacnew, that is, enable package verification through the SigLevel option, and you should be good to go.

For details on the development of pacman and archlinux-keyring, see the blog posts of Allan and Pierre.

Over!

From: http://www.archlinux.org/news/having-pacman-verify-packages/

Vala D-Bus Examples

Vala supports D-Bus inter-process communication using the GDBus API that is part of GLib/GIO since version 2.26.

Vala automatically transforms Vala style lower_case_names to D-Bus style CamelCaseNames behind the scenes. You can use methods, signals, properties in D-Bus objects as if they were Vala objects.

Using GDBus
Server

/* Note: this attribute specifies the _interface_ name.  It
 * is called 'name =' for historical reasons.
 */
[DBus (name = "org.example.Demo")]
public class DemoServer : Object {
 
    private int counter;
 
    public int ping (string msg) {
        stdout.printf ("%s\n", msg);
        return counter++;
    }
 
    public int ping_with_signal (string msg) {
        stdout.printf ("%s\n", msg);
        pong(counter, msg);
        return counter++;
    }
 
    /* Including any parameter of type GLib.BusName won't be added to the
       interface and will return the dbus sender name (who is calling the method) */
    public int ping_with_sender (string msg, GLib.BusName sender) {
        stdout.printf ("%s, from: %s\n", msg, sender);
        return counter++;
    }
 
    public void ping_error () throws Error {
        throw new DemoError.SOME_ERROR ("There was an error!");
    }
 
    public signal void pong (int count, string msg);
}
 
[DBus (name = "org.example.DemoError")]
public errordomain DemoError
{
    SOME_ERROR
}
 
void on_bus_aquired (DBusConnection conn) {
    try {
        conn.register_object ("/org/example/demo", new DemoServer ());
    } catch (IOError e) {
        stderr.printf ("Could not register service\n");
    }
}
 
void main () {
    Bus.own_name (BusType.SESSION, "org.example.Demo", BusNameOwnerFlags.NONE,
                  on_bus_aquired,
                  () => {},
                  () => stderr.printf ("Could not aquire name\n"));
 
    new MainLoop ().run ();
}
valac --pkg gio-2.0 gdbus-demo-server.vala

Client
The methods of the client interface must be defined with throws IOError.

[DBus (name = "org.example.Demo")]
interface Demo : Object {
    public abstract int ping (string msg) throws IOError;
    public abstract int ping_with_sender (string msg) throws IOError;
    public abstract int ping_with_signal (string msg) throws IOError;
    public signal void pong (int count, string msg);
}
 
void main () {
    /* Needed only if your client is listening to signals; you can omit it otherwise */
    var loop = new MainLoop();
 
    /* Important: keep demo variable out of try/catch scope not lose signals! */
    Demo demo = null;
 
    try {
        demo = Bus.get_proxy_sync (BusType.SESSION, "org.example.Demo",
                                                    "/org/example/demo");
 
        /* Connecting to signal pong! */
        demo.pong.connect((c, m) => {
            stdout.printf ("Got pong %d for msg '%s'\n", c, m);
            loop.quit ();
        });
 
        int pong = demo.ping ("Hello from Vala");
        stdout.printf ("%d\n", pong);
 
        pong = demo.ping_with_sender ("Hello from Vala with sender");
        stdout.printf ("%d\n", pong);
 
        pong = demo.ping_with_signal ("Hello from Vala with signal");
        stdout.printf ("%d\n", pong);
 
    } catch (IOError e) {
        stderr.printf ("%s\n", e.message);
    }
    loop.run();
}
valac --pkg gio-2.0 gdbus-demo-client.vala

Type Table

D-Bus Vala Description Example
b bool Boolean
y uint8 Byte
i int Integer
u uint Unsigned Integer
n int16 16-bit Integer
q uint16 Unsigned 16-bit Integer
x int64 64-bit Integer
t uint64 Unsigned 64-bit Integer
d double Double
s string String
v GLib.Variant Variant
o GLib.ObjectPath Object Path
a [] Array ai maps to int[]
a{} GLib.HashTable<,> Dictionary a{sv} maps to HashTable<string, Variant>
() a struct type Struct a(ii) maps to Foo[] where Foo might be defined as
struct Foo { public int a; public int b };

Debugging D-Bus Applications
D-Feet
D-Feet is a graphical D-Bus debugger. This is what our little D-Bus service looks like in D-Feet:

dbus-monitor
Open a terminal and enter:

dbus-monitor

Excerpt from the output showing a property change notification:

signal sender=:1.454 -> dest=(null destination) serial=9 path=/org/example/demo; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "org.example.Demo"
   array [
      dict entry(
         string "pubprop"
         variant             string "1018873421"
      )
   ]
   array [
   ]

Service with D-Bus property change notifications
This example will setup a D-Bus service that can send notifications on the change of properties. (example code partly by Faheem)

The timeout will change the property every few seconds. The notifications can be visualized by the terminal program ‘dbus-monitor’ that comes with most distributions.

[DBus (name = "org.example.Demo")]
public class DemoServer : Object {
 
    public string pubprop { owned get; set; }
 
    private weak DBusConnection conn;
 
    public DemoServer (DBusConnection conn) {
        this.conn = conn;
        this.notify.connect (send_property_change);
    }
 
    private void send_property_change (ParamSpec p) {
        var builder = new VariantBuilder (VariantType.ARRAY);
        var invalid_builder = new VariantBuilder (new VariantType ("as"));
 
        if (p.name == "pubprop") {
            Variant i = pubprop;
            builder.add ("{sv}", "pubprop", i);
        }
 
        try {
            conn.emit_signal (null, 
                              "/org/example/demo", 
                              "org.freedesktop.DBus.Properties", 
                              "PropertiesChanged", 
                              new Variant ("(sa{sv}as)", 
                                           "org.example.Demo", 
                                           builder, 
                                           invalid_builder)
                              );
        } catch (Error e) {
            stderr.printf ("%s\n", e.message);
        }
    }
}
 
public class NotificationsTest : Object {
 
    private DemoServer dserver;
 
    public NotificationsTest () {
        Bus.own_name (BusType.SESSION, "org.example.Demo", BusNameOwnerFlags.NONE,
                      on_bus_acquired, on_name_acquired, on_name_lost);
    }
 
    private void on_bus_acquired (DBusConnection conn) {
        print ("bus acquired\n");
        try {
            this.dserver = new DemoServer (conn);
            conn.register_object ("/org/example/demo", this.dserver);
        } catch (IOError e) {
            print ("%s\n", e.message);
        }
    }
 
    private void on_name_acquired () {
        print ("name acquired\n");
    }  
 
    private void on_name_lost () {
        print ("name_lost\n");
    }
 
    public void setup_timeout () {
        Timeout.add_seconds (4, () => {
            dserver.pubprop = Random.next_int ().to_string ();
            return true;
        });
    }
}
 
void main () {
    var nt = new NotificationsTest ();
    nt.setup_timeout ();
    new MainLoop ().run ();
}
valac --pkg gio-2.0 gdbus-change-notificationst.vala

Over!

From: https://live.gnome.org/Vala/DBusServerSample