调整 GNOME Shell 用户菜单挂起默认为关机

/usr/share/gnome-shell/js/ui/userMenu.js

--- a/usr/share/gnome-shell/js/ui/userMenu.js	2012-08-27 21:27:02.800846936 +0800
+++ b/usr/share/gnome-shell/js/ui/userMenu.js	2012-08-27 21:30:45.310852968 +0800
@@ -596,7 +596,7 @@
         } else if (!this._haveShutdown) {
             this._suspendOrPowerOffItem.updateText(_("Suspend"), null);
         } else {
-            this._suspendOrPowerOffItem.updateText(_("Suspend"), _("Power Off..."));
+            this._suspendOrPowerOffItem.updateText(_("Power Off..."), _("Suspend"));
         }
     },
 
@@ -665,8 +665,8 @@
         item = new PopupMenu.PopupSeparatorMenuItem();
         this.menu.addMenuItem(item);
 
-        item = new PopupMenu.PopupAlternatingMenuItem(_("Suspend"),
-                                                      _("Power Off..."));
+        item = new PopupMenu.PopupAlternatingMenuItem(_("Power Off..."),
+                                                      _("Suspend"));
         this.menu.addMenuItem(item);
         this._suspendOrPowerOffItem = item;
         item.connect('activate', Lang.bind(this, this._onSuspendOrPowerOffActivate));
@@ -734,12 +734,12 @@
 
         if (this._haveSuspend &&
             this._suspendOrPowerOffItem.state == PopupMenu.PopupAlternatingMenuItemState.DEFAULT) {
+            this._session.ShutdownRemote();
+        } else {
             // Ensure we only suspend after locking the screen
             this._screenSaverProxy.LockRemote(Lang.bind(this, function() {
                 this._upClient.suspend_sync(null);
             }));
-        } else {
-            this._session.ShutdownRemote();
         }
     }
 });

Over!

安装 Devhelp 版本的 Valadoc

Valadoc 是一个非常优秀的的在线 Vala 语言 API 参考手册,但是就国内的网络环境使用效果是很不爽的。建议安装 Devhelp 版本至本地,前提是你使用 Devhelp。

安装方法

mkdir -p ~/.local/share/devhelp/books/
mkdir tmp
cd tmp
wget http://heiher.info/sftp/files/valadoc-list.txt
for i in `cat valadoc-list.txt`; do
wget $i && tar -xf `basename $i` -C ~/.local/share/devhelp/books/
done

下载列表 (valadoc-list.txt)

http://www.valadoc.org/alsa/alsa.tar.bz2
http://www.valadoc.org/atasmart/atasmart.tar.bz2
http://www.valadoc.org/atk/atk.tar.bz2
http://www.valadoc.org/avahi-gobject/avahi-gobject.tar.bz2
http://www.valadoc.org/bzlib/bzlib.tar.bz2
http://www.valadoc.org/cairo/cairo.tar.bz2
http://www.valadoc.org/cairo-xcb/cairo-xcb.tar.bz2
http://www.valadoc.org/ccss-1/ccss-1.tar.bz2
http://www.valadoc.org/champlain-0.14/champlain-0.14.tar.bz2
http://www.valadoc.org/champlain-gtk-0.14/champlain-gtk-0.14.tar.bz2
http://www.valadoc.org/clutter-1.0/clutter-1.0.tar.bz2
http://www.valadoc.org/clutter-gst-1.0/clutter-gst-1.0.tar.bz2
http://www.valadoc.org/clutter-gtk-0.10/clutter-gtk-0.10.tar.bz2
http://www.valadoc.org/clutter-gtk-1.0/clutter-gtk-1.0.tar.bz2
http://www.valadoc.org/clutter-json-1.0/clutter-json-1.0.tar.bz2
http://www.valadoc.org/cogl-1.0/cogl-1.0.tar.bz2
http://www.valadoc.org/cogl-pango-1.0/cogl-pango-1.0.tar.bz2
http://www.valadoc.org/colord/colord.tar.bz2
http://www.valadoc.org/curses/curses.tar.bz2
http://www.valadoc.org/dbus-glib-1/dbus-glib-1.tar.bz2
http://www.valadoc.org/Dbusmenu-0.4/Dbusmenu-0.4.tar.bz2
http://www.valadoc.org/DbusmenuGtk3-0.4/DbusmenuGtk3-0.4.tar.bz2
http://www.valadoc.org/dee-1.0/dee-1.0.tar.bz2
http://www.valadoc.org/enchant/enchant.tar.bz2
http://www.valadoc.org/fuse/fuse.tar.bz2
http://www.valadoc.org/gconf-2.0/gconf-2.0.tar.bz2
http://www.valadoc.org/gdk-2.0/gdk-2.0.tar.bz2
http://www.valadoc.org/gdk-3.0/gdk-3.0.tar.bz2
http://www.valadoc.org/gdk-pixbuf-2.0/gdk-pixbuf-2.0.tar.bz2
http://www.valadoc.org/gdk-x11-2.0/gdk-x11-2.0.tar.bz2
http://www.valadoc.org/gdk-x11-3.0/gdk-x11-3.0.tar.bz2
http://www.valadoc.org/gdl-1.0/gdl-1.0.tar.bz2
http://www.valadoc.org/gdl-3.0/gdl-3.0.tar.bz2
http://www.valadoc.org/gdu/gdu.tar.bz2
http://www.valadoc.org/gdu-gtk/gdu-gtk.tar.bz2
http://www.valadoc.org/gedit/gedit.tar.bz2
http://www.valadoc.org/gedit-2.20/gedit-2.20.tar.bz2
http://www.valadoc.org/gio-2.0/gio-2.0.tar.bz2
http://www.valadoc.org/gio-unix-2.0/gio-unix-2.0.tar.bz2
http://www.valadoc.org/glib-2.0/glib-2.0.tar.bz2
http://www.valadoc.org/gmodule-2.0/gmodule-2.0.tar.bz2
http://www.valadoc.org/gnome-keyring-1/gnome-keyring-1.tar.bz2
http://www.valadoc.org/gobject-2.0/gobject-2.0.tar.bz2
http://www.valadoc.org/gssdp-1.0/gssdp-1.0.tar.bz2
http://www.valadoc.org/gstreamer-0.10/gstreamer-0.10.tar.bz2
http://www.valadoc.org/gstreamer-app-0.10/gstreamer-app-0.10.tar.bz2
http://www.valadoc.org/gstreamer-audio-0.10/gstreamer-audio-0.10.tar.bz2
http://www.valadoc.org/gstreamer-base-0.10/gstreamer-base-0.10.tar.bz2
http://www.valadoc.org/gstreamer-cdda-0.10/gstreamer-cdda-0.10.tar.bz2
http://www.valadoc.org/gstreamer-check-0.10/gstreamer-check-0.10.tar.bz2
http://www.valadoc.org/gstreamer-controller-0.10/gstreamer-controller-0.10.tar.bz2
http://www.valadoc.org/gstreamer-dataprotocol-0.10/gstreamer-dataprotocol-0.10.tar.bz2
http://www.valadoc.org/gstreamer-fft-0.10/gstreamer-fft-0.10.tar.bz2
http://www.valadoc.org/gstreamer-interfaces-0.10/gstreamer-interfaces-0.10.tar.bz2
http://www.valadoc.org/gstreamer-net-0.10/gstreamer-net-0.10.tar.bz2
http://www.valadoc.org/gstreamer-netbuffer-0.10/gstreamer-netbuffer-0.10.tar.bz2
http://www.valadoc.org/gstreamer-pbutils-0.10/gstreamer-pbutils-0.10.tar.bz2
http://www.valadoc.org/gstreamer-riff-0.10/gstreamer-riff-0.10.tar.bz2
http://www.valadoc.org/gstreamer-rtp-0.10/gstreamer-rtp-0.10.tar.bz2
http://www.valadoc.org/gstreamer-rtsp-0.10/gstreamer-rtsp-0.10.tar.bz2
http://www.valadoc.org/gstreamer-sdp-0.10/gstreamer-sdp-0.10.tar.bz2
http://www.valadoc.org/gstreamer-tag-0.10/gstreamer-tag-0.10.tar.bz2
http://www.valadoc.org/gstreamer-video-0.10/gstreamer-video-0.10.tar.bz2
http://www.valadoc.org/gtk+-2.0/gtk+-2.0.tar.bz2
http://www.valadoc.org/gtk+-3.0/gtk+-3.0.tar.bz2
http://www.valadoc.org/gtk-vnc-2.0/gtk-vnc-2.0.tar.bz2
http://www.valadoc.org/gtkmozembed/gtkmozembed.tar.bz2
http://www.valadoc.org/gtksourceview-2.0/gtksourceview-2.0.tar.bz2
http://www.valadoc.org/gtksourceview-3.0/gtksourceview-3.0.tar.bz2
http://www.valadoc.org/gudev-1.0/gudev-1.0.tar.bz2
http://www.valadoc.org/gupnp-1.0/gupnp-1.0.tar.bz2
http://www.valadoc.org/gupnp-av-1.0/gupnp-av-1.0.tar.bz2
http://www.valadoc.org/gupnp-dlna-1.0/gupnp-dlna-1.0.tar.bz2
http://www.valadoc.org/gvnc-1.0/gvnc-1.0.tar.bz2
http://www.valadoc.org/hal/hal.tar.bz2
http://www.valadoc.org/hildon-1/hildon-1.tar.bz2
http://www.valadoc.org/hildon-fm-2/hildon-fm-2.tar.bz2
http://www.valadoc.org/javascriptcoregtk-3.0/javascriptcoregtk-3.0.tar.bz2
http://www.valadoc.org/json-glib-1.0/json-glib-1.0.tar.bz2
http://www.valadoc.org/libarchive/libarchive.tar.bz2
http://www.valadoc.org/libbonoboui-2.0/libbonoboui-2.0.tar.bz2
http://www.valadoc.org/libcanberra/libcanberra.tar.bz2
http://www.valadoc.org/libcanberra-gtk/libcanberra-gtk.tar.bz2
http://www.valadoc.org/libdaemon/libdaemon.tar.bz2
http://www.valadoc.org/libepc-1.0/libepc-1.0.tar.bz2
http://www.valadoc.org/libesmtp/libesmtp.tar.bz2
http://www.valadoc.org/libftdi/libftdi.tar.bz2
http://www.valadoc.org/libgda-4.0/libgda-4.0.tar.bz2
http://www.valadoc.org/libgda-report-4.0/libgda-report-4.0.tar.bz2
http://www.valadoc.org/libgdata/libgdata.tar.bz2
http://www.valadoc.org/libglade-2.0/libglade-2.0.tar.bz2
http://www.valadoc.org/libgsf-1/libgsf-1.tar.bz2
http://www.valadoc.org/libgvc/libgvc.tar.bz2
http://www.valadoc.org/libmagic/libmagic.tar.bz2
http://www.valadoc.org/libnl-1/libnl-1.tar.bz2
http://www.valadoc.org/libnl-2.0/libnl-2.0.tar.bz2
http://www.valadoc.org/libnl-3.0/libnl-3.0.tar.bz2
http://www.valadoc.org/libnotify/libnotify.tar.bz2
http://www.valadoc.org/liboobs-1/liboobs-1.tar.bz2
http://www.valadoc.org/libosinfo-1.0/libosinfo-1.0.tar.bz2
http://www.valadoc.org/libosso/libosso.tar.bz2
http://www.valadoc.org/libpanelapplet-2.0/libpanelapplet-2.0.tar.bz2
http://www.valadoc.org/libpeas-1.0/libpeas-1.0.tar.bz2
http://www.valadoc.org/libpq/libpq.tar.bz2
http://www.valadoc.org/libproxy-1.0/libproxy-1.0.tar.bz2
http://www.valadoc.org/librsvg-2.0/librsvg-2.0.tar.bz2
http://www.valadoc.org/libsoup-2.2/libsoup-2.2.tar.bz2
http://www.valadoc.org/libsoup-2.4/libsoup-2.4.tar.bz2
http://www.valadoc.org/libusb/libusb.tar.bz2
http://www.valadoc.org/libusb-1.0/libusb-1.0.tar.bz2
http://www.valadoc.org/libvirt-gconfig-1.0/libvirt-gconfig-1.0.tar.bz2
http://www.valadoc.org/libvirt-glib-1.0/libvirt-glib-1.0.tar.bz2
http://www.valadoc.org/libvirt-gobject-1.0/libvirt-gobject-1.0.tar.bz2
http://www.valadoc.org/libwnck-1.0/libwnck-1.0.tar.bz2
http://www.valadoc.org/libwnck-3.0/libwnck-3.0.tar.bz2
http://www.valadoc.org/libxml-2.0/libxml-2.0.tar.bz2
http://www.valadoc.org/linux/linux.tar.bz2
http://www.valadoc.org/loudmouth-1.0/loudmouth-1.0.tar.bz2
http://www.valadoc.org/lua/lua.tar.bz2
http://www.valadoc.org/mx-1.0/mx-1.0.tar.bz2
http://www.valadoc.org/mysql/mysql.tar.bz2
http://www.valadoc.org/orc-0.4/orc-0.4.tar.bz2
http://www.valadoc.org/pango/pango.tar.bz2
http://www.valadoc.org/pangocairo/pangocairo.tar.bz2
http://www.valadoc.org/pixman-1/pixman-1.tar.bz2
http://www.valadoc.org/poppler-glib/poppler-glib.tar.bz2
http://www.valadoc.org/posix/posix.tar.bz2
http://www.valadoc.org/purple/purple.tar.bz2
http://www.valadoc.org/raptor/raptor.tar.bz2
http://www.valadoc.org/rasqal/rasqal.tar.bz2
http://www.valadoc.org/readline/readline.tar.bz2
http://www.valadoc.org/rest-0.6/rest-0.6.tar.bz2
http://www.valadoc.org/rest-0.7/rest-0.7.tar.bz2
http://www.valadoc.org/rest-extras-0.6/rest-extras-0.6.tar.bz2
http://www.valadoc.org/sdl/sdl.tar.bz2
http://www.valadoc.org/sdl-gfx/sdl-gfx.tar.bz2
http://www.valadoc.org/sdl-image/sdl-image.tar.bz2
http://www.valadoc.org/sdl-mixer/sdl-mixer.tar.bz2
http://www.valadoc.org/sdl-net/sdl-net.tar.bz2
http://www.valadoc.org/sdl-ttf/sdl-ttf.tar.bz2
http://www.valadoc.org/spice-client-glib-2.0/spice-client-glib-2.0.tar.bz2
http://www.valadoc.org/spice-client-gtk-3.0/spice-client-gtk-3.0.tar.bz2
http://www.valadoc.org/spice-protocol/spice-protocol.tar.bz2
http://www.valadoc.org/sqlite3/sqlite3.tar.bz2
http://www.valadoc.org/taglib_c/taglib_c.tar.bz2
http://www.valadoc.org/telepathy-glib/telepathy-glib.tar.bz2
http://www.valadoc.org/tiff/tiff.tar.bz2
http://www.valadoc.org/tracker-indexer-module-1.0/tracker-indexer-module-1.0.tar.bz2
http://www.valadoc.org/twitter-glib-1.0/twitter-glib-1.0.tar.bz2
http://www.valadoc.org/udisks2/udisks2.tar.bz2
http://www.valadoc.org/unique-1.0/unique-1.0.tar.bz2
http://www.valadoc.org/unity/unity.tar.bz2
http://www.valadoc.org/unity-trace/unity-trace.tar.bz2
http://www.valadoc.org/v4l2/v4l2.tar.bz2
http://www.valadoc.org/vte/vte.tar.bz2
http://www.valadoc.org/vte-2.90/vte-2.90.tar.bz2
http://www.valadoc.org/webkit-1.0/webkit-1.0.tar.bz2
http://www.valadoc.org/x11/x11.tar.bz2
http://www.valadoc.org/xcb/xcb.tar.bz2
http://www.valadoc.org/xtst/xtst.tar.bz2
http://www.valadoc.org/zeitgeist-1.0/zeitgeist-1.0.tar.bz2

Over!

来自国内行货 Android 手机 GPS 配置文件

我的 HTC Evo 4G 刷了 CM 7.2 ROM 后 GPS 就不好用了,使用 GPS Test 在室外竟然都一颗星也找不到。定位问题应该在 /etc/gps.conf 配置文件不适合在国内使用,原因我想大家都懂的。

从国内行货手机里复制了个配置文件,室外基本上可以秒定了。

NTP_SERVER=asia.pool.ntp.org
XTRA_SERVER_1=http://xtra1.gpsonextra.net/xtra.bin
XTRA_SERVER_2=http://xtra2.gpsonextra.net/xtra.bin
XTRA_SERVER_3=http://xtra3.gpsonextra.net/xtra.bin
C2K_HOST=default
C2K_PORT=6066
DEFAULT_AGPS_MODE=MS_BASED
PHONE_TYPE=CDMA

Over!

内存屏障是什么?

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

内存屏障的分类
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!

加速 ModemManager 探测 ZTE R518 设备

由于 ZTE R518 手机包含多路串口设备节点,而 ModemManager 只使用其中的一路,其余会影响探测速度。使用下面的 udev 规则可加速 ModemManager 枚举 R518 的速度。

/etc/udev/rules.d/80-zte-r518.rules

# Heiher <admin@heiher.info>
#
 
SUBSYSTEM=="usb", ACTION=="add", ENV{ID_VENDOR_ID}=="19d2", ENV{ID_MODEL_ID}=="1358", RUN+="/sbin/modprobe usbserial vendor=0x19d2 product=0x1358"
SUBSYSTEM=="usb", ACTION=="remove", ENV{ID_VENDOR_ID}=="19d2", ENV{ID_MODEL_ID}=="1358", RUN+="/sbin/modprobe -r usbserial"
 
SUBSYSTEM=="tty", ACTION=="add|change", ENV{ID_VENDOR_ID}=="19d2", ENV{ID_MODEL_ID}=="1358", ENV{ID_USB_INTERFACE_NUM}=="01|02", RUN+="/bin/rm %N"

Over!