Planet DebianTW

July 04, 2008

jserv

不再囉唆:NetBSD 簡化 BSD 授權條款

儘管絕大多數的開發者都知曉 BSD 授權條款較為寬鬆,沒有 GNU GPL 本質上 "copyleft" 的「病毒式」感染性,但實務應用仍有值得推敲之處。NetBSD 基金會近日甚至宣佈,進一步簡化其使用多年的 BSD 授權條款,相較於繁瑣的 GNU GPLv3,NetBSD 此舉可說追趕 FreeBSD 與 OpenBSD,樹立 BSD 授權的「自由派」訴求。 BSD License 為 "Berkeley Software Distribution license" 的縮寫,顧名思義,源於加州柏克萊大學的 BSD 一系列的軟體,最早的著作權人為 Regents of the University of California'(加州大學董事會),BSD 授權條款本身相當清楚,最初的版本有四個條款,也就是規範被授權人的條件限制,如下: Redistributions of source code...

by jserv at July 04, 2008 03:53 AM

July 03, 2008

tsung

jserv

取得 GNU/Linux 行程的執行檔路徑

本文試著探討 GNU/Linux 於執行時期 (run-time) 的行程 (Process) 如何取得執行檔路徑,並探討 /proc/self/exe 的機制與其應用。 進入主題前,我們該來思考本文標題: 「取得 Linux 行程的執行檔路徑,有什麼好處?在什麼場合需要?」 這個問題最好的答案,就是看看真實需求。筆者七年前曾撰寫過一篇短文 [親手打造 Floppy Linux 環境],在談及 GNU/Linux 剪裁的過程中,提到 [busybox] 得以將若干工具透過 symbolic link 到 /bin/busybox、且能於執行時期正確依據名稱挑選 applet 並執行的原理,就是透過 argv[0],也就是「執行時期的名稱」。具體來說,當我們在 shell 中執行 cp、cat、chown 等指令時,busybox 會將包含「名稱」的 arvg[0] 丟給 run_applet_by_name() 去解析名稱,再去找對應的實做,並儘可能讓各工具程式達到最大的程式碼可重用性,甚至免去動態連結的負擔。 由於該文年代久遠 (注意:筆者認為現在將...

by jserv at July 03, 2008 02:53 PM

July 02, 2008

Tetralet

Gtk+2 元件的記憶體用量

如果您是用 ThunderBird 來收發電子郵件的話,您可能會注意到一個有趣的現象:不管您執行了多次 ThunderBird,系統並不會因而開出多個 ThunderBird 視窗。ThunderBird 在啟動時的同時似乎會進行什麼自我偵測,以避免系統上因同時存在多個 ThunderBird 行程而導致無謂得浪費寶貴系統資源。

個人把這種機制叫做『Single Process (暫)』。


LilyTerm
已於 0.9.4 版開始支援 Single Process。此後,不管執行多少次 LilyTerm,新的 LilyTerm 將只是由第 1 個 LilyTerm 所分出來的新視窗。如果您用 ps 指令來查看的話,您會發現系統裡將只有 1 個 LilyTerm 行程。這也就是為什麼我叫它 Single Process 的原因。

舉例來說,在個人的電腦上,一個新開啟的 LilyTerm 行程將會佔用掉約 9MB 的記憶體:
$ ps aux | grep lilyterm
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tetralet  2531  0.8  1.7  30220  9164 pts/1    S    00:01   0:00 lilyterm
但改為使用 Single Process 後,另一個新開啟的 LilyTerm 行程將只會多佔用 172KB
$ ps aux | grep lilyterm
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

tetralet  2531  0.2  1.8  30268  9336 pts/1    S    00:01   0:00 lilyterm

也就是說,原本一個新開啟的 LilyTerm 行程應該是會再額外佔用 9MB 的記憶體,啟用了 Single Process 機制後一下子減少到只需 172KB!這真的是太驚人了。世界上所有軟體應該把 Single Process 機制列為標準備配才是。

但是,天底下真的有那麼好的事情嗎?

應用程式的記憶體佔用量

首先,如果您查看一下,您會發現 LilyTerm 的 0.9.4 版的執行檔大小約為 76KB,但載入到了記憶體裡就變成了 9MB。我想您應該猜得到,這是因為 LilyTerm 在載入記憶體的同時,也會同時載入像是 libclibXft libgtklibvte 等等函式庫的關係。您可以利用 ldd 指令來查看 lilyterm 會連結到哪些函式庫。
註:
其實新開啟的 LilyTerm 行程並不會佔用到那麼多記憶體。使用 ps 指令並不能精確得指出應用程式實際的記憶體使用量。後文將有說明。

另外,下文中所有的測試數據和您系統所安裝的 字型/輸入法/編譯 方式都有很大關係,所以在您的電腦上數據也許會有一些小出入。
但人們的想法裡,程式在載入記憶體後,會先展開,然後把一堆函式庫抓進來,這也是為什麼明明只有 76KBLilyTerm 在載入到了記憶體裡就變成了 9MB 的主要原因。也就是說,執行檔越大、函式庫連結越多的應用程式,應該會佔用較多的記憶體。

但讓我們看看下面的例子。如果您用 ldd 指令來查看 evilvtelilyterm 這兩個極相似的程式的話,您會發現兩者會連結到的函式庫並沒有什麼分別,但載到記憶體的結果卻大異其趣:
$ ls -l
-rwxr-xr-x 1 root root 76284 2008-07-01 19:10 /usr/bin/lilyterm
-rwxr-xr-x 1 root root 28636 2008-05-28 17:24 /usr/bin/evilvte


$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

tetralet  2550  0.8  2.1  54988 11240 pts/1    S    00:01   0:00 evilvte

tetralet  2531  0.8  1.7  30220  9164 pts/1    S    00:01   0:00 lilyterm
LilyTerm 的執行檔大小約為 evilvte 的 3 倍,也比 evilvte 提供了更多功能,所以 evilvte 理論上應該比較輕巧才是,但載入記憶體後 evilvte 卻比 LilyTerm 佔用了更多的記憶體。為什麼?這並不合理呀?

Gtk 應用程式的記憶體使用狀況

也許我們利用另一個 vte based 的 X Terminal Emulator - xfce4-terminal 來說明會比較清楚。以下為使用不同參數來啟動 xfce4-terminal 的結果:
$ ps aux | grep xfce4-terminal
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

tetralet  2512  0.7  2.4  56480 12732 pts/1    S    00:01   0:00 xfce4-terminal
tetralet  2603  1.0  2.0  31572 10696 pts/1    S    00:03   0:00 xfce4-terminal --hide-toolbars --hide-menubar
在將 toolbar 及 menubar 隱藏起來後,xfce4-terminal 所佔用的記憶體明顯變少了 - 甚至比 evilvte 還小。也就是說,GNU/Linux 在載入應用程式時,並不是一股腦得把所有函式庫全載進來:只有實際有使用到的元件才會被 Linux 所載入,這的確是相當聰明有彈性的做法。

因此,我們可以猜到:evilvte 預設會顯示 statusbar,這也就是它比 LilyTerm/xfce4-terminal 佔用更多記憶體的主因。GNU/Linux 的應用程式並不是執行檔小,它就會佔用較少的記憶體,一切都要看實際的狀況而定。

libvte 癡肥?

以下是一個極簡版的 Gtk 應用程式。除了一個單一視窗外什麼都沒有:
#include <gtk/gtk.h>

int main( int   argc,
          char *argv[])
{
        gtk_init (&argc, &argv);

        GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        g_signal_connect (G_OBJECT(window), "delete_event",
                          G_CALLBACK(gtk_main_quit), NULL);
        gtk_widget_show_all(window);
        gtk_main();
        return 0;
}

這個 gtk_demo 程式在載入後約佔用 4.2MB 的記憶體:
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tetralet  2627  0.0  0.8  12320  4232 pts/1    S    00:05   0:00 ./gtk_demo
然後,利用以下程式碼,我們就可以大略估算出:如果再多載入單一 vte 元件,將會比 gtk_demo 再多佔用掉約 3.8MB 的記憶體:
#include <vte/vte.h>

int main( int   argc,
          char *argv[])
{
        gtk_init (&argc, &argv);

        GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        g_signal_connect (G_OBJECT(window), "delete_event",
                          G_CALLBACK(gtk_main_quit), NULL);
        GtkWidget *vte = vte_terminal_new();
        vte_terminal_fork_command(VTE_TERMINAL(vte), NULL, NULL,
                                  NULL, NULL, TRUE, TRUE, TRUE);

        gtk_container_add(GTK_CONTAINER(window), vte);
        gtk_widget_show_all(window);
        gtk_main();
        return 0;
}

做為對照組,如果再多載入單一 gtk_entry 元件(Gtk 的輸入欄位元件)後,將會比 gtk_demo 再多佔用掉約 3.4MB 的記憶體:
#include <gtk/gtk.h>

int main( int   argc,
          char *argv[])
{
        gtk_init (&argc, &argv);

        GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        g_signal_connect (G_OBJECT(window), "delete_event",
                          G_CALLBACK(gtk_main_quit), NULL);
        GtkWidget *entry = gtk_entry_new();
        gtk_container_add(GTK_CONTAINER(window), entry);
        gtk_widget_show_all(window);
        gtk_main();
        return 0;
}

以上的程式其實際執行結果如下:
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tetralet  2627  0.0  0.8  12320  4232 pts/1    S    00:05   0:00 ./gtk_demo

tetralet  2667  0.8  1.5  38164  7828 pts/1    S    00:05   0:00 ./entry_demo

tetralet  2648  0.4  1.5  29532  8068 pts/1    S    00:05   0:00 ./vte_demo
也就是說,若單看記憶體用量的話,載入一個像 vte 那麼複雜的元件也等同載入一個 entry 元件再多一點點而己。請別忘了,比起 entry_demo 來,vte_demo 可還多載入了一個 libvte.so.9 函式庫呢!也就是說,光以記憶體用量來說,或許 libvte 會比 gtk_entry 元件更為輕巧呢!libvte 癡肥?個人認為是有點苛刻了。

Gtk+2 元件的記憶體使用機制

看到這裡您可能會很訝異:載入 1 個 gtk_entry 元件會佔用掉約 3.4MB 的記憶體。那麼一個設計稍微複雜的應用程式,將會佔用掉多少的記憶體?那未免太誇張了吧?

我們不妨來試驗一下。以下是一個裡面放了 100gtk_entry 元件的單一視窗:
#include <gtk/gtk.h>

int main( int   argc,
          char *argv[])
{
        gtk_init (&argc, &argv);
        int i;

        GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        g_signal_connect (G_OBJECT(window), "delete_event",
                          G_CALLBACK(gtk_main_quit), NULL);
        GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
        for (i=0;i<100;i++)
        {
                GtkWidget *entry = gtk_entry_new();
                gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 0);
        }

        gtk_container_add(GTK_CONTAINER(window), vbox);
        gtk_widget_show_all(window);
        gtk_main();
        return 0;
}
我們比較在一個視窗裡放入了 1 個及 100 個 gtk_entry 元件看執行後會佔用的記憶體會是多少:
$ ps aux | grep entry_demo
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

tetralet  2667  0.8  1.5  38164  7828 pts/1    S    00:05   0:00 ./entry_demo
tetralet  2668  2.0  1.5  38412  8068 pts/1    S    00:05   0:00 ./entry_demo_100
結論是,就算多了 99 個 gtk_entry 元件,記憶體用量只多增加了 240KB,平均起來也只是 2.4KB。也就是說,Linux 不但會視情況載入必要的元件,且 Gtk+ 的元件之間還會共用記憶體

模擬 Single Process 的情形?

那麼,我們模擬在 Single Process 的狀況下,一次會呼叫出 100 個視窗會怎麼樣?
#include <gtk/gtk.h>

int main( int   argc,
          char *argv[])
{
        gtk_init (&argc, &argv);
        int i;

        for (i=0;i<100;i++)
        {
                GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
                g_signal_connect (G_OBJECT(window), "delete_event",
                                  G_CALLBACK(gtk_main_quit), NULL);
                GtkWidget *entry = gtk_entry_new();
                gtk_container_add(GTK_CONTAINER(window), entry);
                gtk_widget_show_all(window);
        }

        gtk_main();
        return 0;
}
結果如下:
$ ps aux | grep entry_demo
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

tetralet  2667  0.8  1.5  38164  7828 pts/1    S    00:05   0:00 ./entry_demo
tetralet  2668  2.0  1.5  38412  8068 pts/1    S    00:05   0:00 ./entry_demo_100
tetralet  2669  4.4  1.6  38948  8584 pts/1    S    00:05   0:01 ./entry_demo_100_window
結論是,就算是一次叫出 100 個視窗,只比原本的單一視窗多出了 756KB 的記憶體。Gtk+ 的元件就算是在多視窗之下還是會共享記憶體。

Single Process vs. Separate Process

那麼,讓我們比較一下 Single Process 和 Separate Process 之間的差異吧!以下是會以單一 Process 產生 100 獨立 vte 視窗的程式:
#include <vte/vte.h>

int main( int   argc,
          char *argv[])
{
        gtk_init (&argc, &argv);
        int i;

        for (i=0;i<100;i++)
        {
                GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
                g_signal_connect (G_OBJECT(window), "delete_event",
                                  G_CALLBACK(gtk_main_quit), NULL);
                GtkWidget *vte = vte_terminal_new();
                vte_terminal_fork_command(VTE_TERMINAL(vte), NULL, NULL,
                                          NULL, NULL, TRUE, TRUE, TRUE);
                gtk_container_add(GTK_CONTAINER(window), vte);
                gtk_widget_show_all(window);
        }
        gtk_main();
        return 0;
}

以下是其記憶體使用量前後比較表:
             total       used       free     shared    buffers     cached
Mem:        515596     111572     404024          0       5648      49588
-/+ buffers/cache:      56336     459260
Swap:       431824          0     431824

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tetralet  2559  1.0  2.2  33216 11544 pts/1    S    00:40   0:05 ./vte_demo_100
tetralet  3050  0.0  0.5   5388  2780 pts/33   Ss+  00:41   0:00 /bin/bash x 100

             total       used       free     shared    buffers     cached
Mem:        515596     316172     199424          0       8020      52060
-/+ buffers/cache:     256092     259504
Swap:       431824          0     431824
我們可以看到,這個程式執行後約略會吃掉 188MB 的記憶體,且十之八九都是被 bash 給佔用掉的,因為 vte_demo_100 本身只佔用了 11MB 的記憶體。

然後,我們用以下的指令跑看看一次跑 100 個獨立的 vte_demo,看看會佔用掉多少的記憶體:
$ perl -e 'system("./vte_demo&") for (1...100);'
其結果如下:
             total       used       free     shared    buffers     cached
Mem:        515596     111820     403776          0       5896      49588
-/+ buffers/cache:      56336     459260
Swap:       431824          0     431824

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
4411 tetralet  17   0 29536 8060 5996 S  0.0  1.6   0:00.16 vte_demo x 100
tetralet  3050  0.0  0.5   5388  2780 pts/33   Ss+  00:41   0:00 /bin/bash x 100

             total       used       free     shared    buffers     cached
Mem:        515596     505120      10476          0      10796      52048
-/+ buffers/cache:     442276      73320
Swap:       431824          0     431824
雖然用 free 指令並不是很精確的估算方式,畢竟系統又不是只在跑這一隻程式。但我們大略可以看出來,跑 100 個獨立的 entry_demo 會佔用掉約 385MB 的記憶體,若再扣掉 bash 所佔用掉的 188MB 的記憶體,我們可以估算出來 entry_demo 約莫是一個 Process 佔用 2MB 的記憶體。雖然比原本的 8MB x 100 節省了不少,但遠不如 Single Process 的 100 個視窗只佔用掉 11MB 的記憶體來得節省。

也就是說,在各個 Seperate process 之間也是會分享記憶體,但其效益遠不如 Single Process 來得大。

Gtk+2 不同的元件間的記憶體使用機制

您可能會很好奇:那麼 gtk_entryvte 是不是也會用享記憶體呢?讓我們用以下程式測試一下吧:
#include <vte/vte.h>

int main( int   argc,
          char *argv[])
{
        gtk_init (&argc, &argv);

        GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        g_signal_connect (G_OBJECT(window), "delete_event",
                          G_CALLBACK(gtk_main_quit), NULL);
        GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
        GtkWidget *entry = gtk_entry_new();
        gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 0);
        GtkWidget *vte = vte_terminal_new();
        vte_terminal_fork_command(VTE_TERMINAL(vte), NULL, NULL,
                                  NULL, NULL, TRUE, TRUE, TRUE);

        gtk_box_pack_start(GTK_BOX(vbox), vte, TRUE, TRUE, 0);
        gtk_container_add(GTK_CONTAINER(window), vbox);
        gtk_widget_show_all(window);
        gtk_main();
        return 0;
}
結果如下:
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tetralet  2627  0.0  0.8  12320  4232 pts/1    S    00:05   0:00 ./gtk_demo
tetralet  2667  0.8  1.5  38164  7828 pts/1    S    00:05   0:00 ./entry_demo
tetralet  2648  0.4  1.5  29532  8068 pts/1    S    00:05   0:00 ./vte_demo
tetralet  2628  0.7  1.9  54464 10272 pts/1    S    00:05   0:00 ./gtk_demo_vte+entry
也就是說,Gtk+2 就算是不同元件之前也是會用享記憶體!真實在太驚人了。

Linux 的記憶體分配方式

最後,筆者想提一下的是 Linux 記憶體分配方式。請參考以下程式:
#include <gtk/gtk.h>

int main( int   argc,
          char *argv[])
{
        gtk_init (&argc, &argv);

        GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        g_signal_connect (G_OBJECT(window), "delete_event",
                          G_CALLBACK(gtk_main_quit), NULL);
        gtk_widget_show_all(window);
        gpointer mem = g_malloc0(100*1024*1024);
        gtk_main();
        return 0;
}
我們跟系統要了 100MB 的空白記憶體。這時您可能會心想:如果多跑幾隻類似的惡搞程式,系統的記憶體很快就不夠用了。但實際執行結果如下:
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tetralet  2627  0.0  0.8  12320  4232 pts/1    S    00:05   0:00 ./gtk_demo
tetralet  2647  0.1  0.8 114724  4236 pts/1    S    00:05   0:00 ./mem_demo
在上例中,雖然 mem_demogtk_demo 多要求了 100MB 的記憶體,但最後 mem_demo 實際上只比 gtk_demo 多佔用了 4K 的記憶體。我們可以猜到的是:Linux 不管應用程式請求了多少記憶體,它只有在必要時才會真的把記憶體分配給應用程式。這也就是 Linux 記憶體管理十分了不起的地方。

LilyTerm vs. evilvte vs. xterm vs. urxvt vs. mlterm 小比較

因此,或許我們可以再替 Gtk+2 平反一下。

個人的 X 預設是開了 6 個虛擬桌面,習慣上每個桌面會擺一個 LilyTerm 在跑。若假設每個 LilyTerm 都開啟了 2 個分頁,我就一共開了 12 個 Terminal 在跑了。因此,敝人就想拿幾個常用的 X Terminal Emulator 測測看在此情況下,它們的記憶體使用量了: 

支援
分頁
Single
Process
執行檔大小
測試方式 行程大小
測試結果
LilyTerm

76KB
2 分頁 x 5 視窗 11,804K x  1
21,228K
xterm

319KB
10 視窗
2,836K x 10
22,804K
mlterm 291KB
2 Pty x 5 視窗 6,384K x  5
27,676K
urxvt
1,226KB
2 分頁 x 5 視窗 6,372K x  5
27,964K
evilvte
28KB
2 分頁 x 5 視窗 11,552K x  5
35,532K
vte_demo
4KB
10 視窗 8,228K x 10
38,600K
註: 測試環境:Celeron 850 + RAM 512MB。
全數使用程式預設值
mlterm 可用 <Ctrl><F1> 來開啟一個新的 Pty 視窗。
其中,xterm 真的是驚人的輕巧,但由於 LilyTerm 支援了 Single Process,所以在此情況下還是能略勝 xterm 一籌。但 vte_demo 則由於既不支援分頁也不支援 Single Process 只好敬陪未座了。

我們可以發現,Gtk+2 based 的應用程式的確會佔用比較多的記憶體空間,也容易給人不夠輕巧的負面觀感。但考慮到 Gtk+2 對於多國語系、輸入法、字型、以及它提供了程式設計師更簡易的設計方式,那麼 Gtk+2 會不夠輕巧也是情有可原的。如果有人嫌 Gtk+2 不夠輕巧,所以重新開發具有相同特性(多國語系、字型、輸入法、佈景主題、元件眾多、易學易用…等等)的 TooKit,能設計得比 Gtk+2 更輕巧嗎?個人卓實抱持著保留的態度。

反過來說,既然 xterm 那麼輕巧,那麼 LilyTerm 就一無是處了嗎?個人的答案也是抱持著保留的態度。
我們可以看到:Gtk+2 的程式設計師只要加把勁,其實也可以將程式設計到和最輕巧的程式一較上下。

我想人們在選擇應用軟體時應該不會只考慮到程式是否夠輕巧,其它像是穩定度、功能、介面、操作習慣…都是考慮的要素之一。個人並不認為在 xterm 之前,LilyTerm/mlterm/ urxvt 就會失去了它的競爭力。

Single Process 真的是一種可行的方式!

由以上測試得知,一些像是 X Terminal Emulator 之類我們可能會開多個視窗的應用程式,的確是應該支援 Single Process,它對節省記憶體所帶來的效益可以說是立竿見影。如果您想挑選順手的 X Terminal Emulator,個人認為應該要把 Single Process 納入考量,它的確是個殺手級的功能!

不過,Single Process 也並不是百利無害 - 如果其中一個視窗當掉了,那麼該 Process 下的所有視窗將會隨之崩潰。也就是說,支援 Single Process 至少本身要夠穩定才行,否則效果將會是適得其反 - 這也是看到支援 Single Process 的程式的同時所該慎重得納入考量的地方。

by Tetralet at July 02, 2008 05:26 PM

tsung

July 01, 2008

jserv

推薦「E-GI建築師事務所實習報告」

最近,放了從求學、職場生涯以來,最長的一次休假。這整整半年的時間內,試著去接觸不同層面的人事物,認識了 egi、閱讀了她豐富的 [E-GI建築師事務所實習報告],從旁探訪她的內心世界,謹此推薦給各位朋友。 有個頗有成就的舅舅任教於台大土木系,小時曾多次耳聞他參與北二高設計與整體規劃的花絮,當時每回都聽得很入迷,但或許覺得自己比較適合敲鍵盤,而不是碰尺規,所以選擇資訊系就讀。大學時代,曾與一位多才多藝且出眾的建築系女生交往,自此交融著對於建築設計的愛好,去建築系館約會時,往往則在這古色古香的建築與多元的設計呈現所傾倒。 事實上,軟體業界的 Architect 這個名詞就是從建築業界借用來的,整個軟體工程的目標更可說是建築設計的抽象呈現:軟體開發如同建築設計,過程中,得針對整體需求、分析、設計、實作、佈署等各項工作流程之不同觀點予以呈現,也就是軟體系統之「塑模」(modeling)。至今,我還記得當時在成大附近的住所,翻閱她帶來 Christopher Alexander 在 1970 年代的大作《A Pattern Language: Town, Building,. Construction》,予我極大的共鳴。 但建築不全然是工程,當談及建築,不免會聯想到「空間感」一詞,是為人們的精神世界鋪就的一條通向終極的理想道路,駐足於此,心境頓時得到永恆的寧靜與祥和,好似,一門之隔卻的有兩個世界。也因此,建築設計是人們內心世界的體驗、感情的記錄,予以具象呈現,偶然在 funP 上瞥見 egi 的文章,按圖索驥尋出其文章的脈絡,不乏詼諧的趣事、情感的轉折與猶豫徘徊,而隱約有著設計人一貫的執著與敏感,或許不顯現於圖文,但存於斯。 從舅舅與前女友身上,大概知曉建築業的生活方式,所以對 egi 的文章偶投以會心一笑與祝福,畢竟這個行業是如此嚴肅又切近我們的生活。其中,最有感觸的文章大概是 [ 230公里的風景] 一文,標題取自於台南到雲林麥寮、花費四個多小時的 230 公里路程。人生際遇往往可用煽情的字句,去誇飾情緒的波瀾壯闊,一如被連續劇養成的感官表現,但平凡中見真情,生命的可貴因此美麗,也因而厚實,我想,egi 的文字就屬於後者,再搭配獨特的圖片更具張力。[ 230公里的風景] 一文取鏡頗耐人尋味,營造出遠離塵囂、反璞歸真之感,又適時以「無政府狀態的張貼模式」凸顯文化與自然環境的對比。很喜歡「波光嶙峋,恰是閑美」前後幾張圖,或許讀者可得以如南台灣普照的陽光一般。 egi 的 [自我介紹] 大概說明了一切: 喜歡畫畫,但是不是藝術家。 喜歡發呆,但是腦袋總塞爆想法。 喜歡,一切。...

by jserv at July 01, 2008 10:18 AM

觀察 Linux 的虛擬記憶體

延續 [尋幽訪勝話系統--以 Linux 探索軟硬體整合設計] 的演講,要觀察 GNU/Linux 運作時期的虛擬記憶體 (Virtaul Memory,以下簡稱 vm),其實沒有想像中的難。首先,可透過 vmstat 工具程式,執行方式如下: $ vmstat -S m procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa 1 0...

by jserv at July 01, 2008 08:03 AM

dken

jserv

httping : 針對 HTTP Request 的仿 ping 程式

[httping] 這個程式非常有意思,能夠以類似 ping 工具程式的方式,將 HTTP Request 的回應情況,呈現給操作者,簡介如下: Give it an url, and it'll show you how long it takes to connect, send a request and retrieve the reply (only the headers). Be aware that the transmission across the network also...

by jserv at July 01, 2008 03:11 AM

演講:快快樂樂學 GNU Debugger (gdb) Part I + II [台中]

幾個月前,在台南舉辦演講:快快樂樂學 GNU Debugger (gdb) [Part I] 與 [Part II],現在也有台中的場次,詳情可見酷!學園的 [討論區],摘錄如下: 簡介:期望使聽者得以透過 GNU Debugger (gdb) 來加速系統開發與分析,讓這個臥在硬碟深處許久的強力程式,激發其威力。本議程捨棄過往教條式的介紹形式,延續「深入淺出 HelloWorld」系列的「作中學」途徑逐一探討使用情境與案例分析 議程主題: Why - 為何我們該善用 Debugger? Who - 誰會因為熟悉 Debugger 而受益? What - 史上最強大的 Debugger -- gdb 與一系列系統軟體 Where - 利用 Debugger 的場合 How -...

by jserv at July 01, 2008 02:05 AM

June 30, 2008

jserv

追憶似水年華

眾鳥高飛盡,孤雲獨去閑 相看兩不厭,只有敬亭山 出自詩仙李白的〈獨坐敬亭山〉,唐朝天寶十二年,凝望著幽靜秀麗的敬亭山,但覺山景也正含情脈脈地回看自己,彷彿兩者已有種默契,是此,詩仙吟出了這首千古絕響。博學精通國史古籍的家母為我命名「敬群」,寓意「敬業樂群」,而次年來到這個花花世界的親妹妹則被命名為「敬婷」,即取於〈獨坐敬亭山〉的最後兩句,並標注「女」字旁表女兒身。今天是妹妹二十六歲生日,取出相簿翻閱我們兒時的照片,竟陷入無限的追憶迴路中。 因為我們兩個小鬼都在六月份出生 (11 日與 30 日),所以雙親乾脆就買一份蛋糕,同時為我們慶生,照片是在苗栗老家的客廳中,兄妹滿心期待地望著生日蛋糕,妹妹當時 3 歲,如紅色蠟燭所示,而右邊的蠟燭是青的,表示我的年紀滿 3 + 1 歲,這大概是少數我們充滿歡笑的合影。妹妹的乳名叫做「小美」,在客家話裡頭很常見,不過,也可說是七次登臨敬亭山、留下了人山兩不厭的太白式浪漫的展現,她的成長歷程一度是很順利,也聰明討人歡喜,有大量的創作與活動,但這十幾年來,過得很痛苦,自限於象牙塔中,有如中世紀的武士,獨自對抗著難為我們所察的敵人,而身心俱疲。 在年幼時,受到過度保護、與外界隔絕的我,幾乎不知什麼是朋友,與同學的關係僅限於課堂,而妹妹則是唯一的玩伴,只要鑰匙兒童一回家,兄妹倆立刻拉下鐵門簾,要不看電視、玩積木、談天、下棋,就是各自讀書,偶爾,我們一同打水仗、打電腦、拼圖、繪畫等等,那些是兒時美好的記憶,我們很少吵架,感情也很好。過去,妹妹在許多層面的表現一直大幅超越我,諸如功課、繪畫、鋼琴、身高、人緣,而處於身旁的我,就好像是個弟弟。後來發生了許多轉折,在我離鄉背井到台中唸書時發生的連鎖效應,總之,一切變調了,我幾乎無法與人談論妹妹所發生的事情,以及我們家庭的處理態度。 山脈對地球來說,只是短暫的穩定,是沈積與地質運動的產物,對生命短暫如飛絮的我們來說,就跟其他自然景物一般,無所謂雋永與否。但,若見到我們無法接受、或不喜愛的景物,可能牽引而生煩躁的心情,若所見者在我們的主觀感受,覺得它是美好的,生命本身即可能被牽引而進入美好的狀態。詩仙看山就是這樣的心境,產生了心理的變化,並緩緩帶領生命進入另一種難以言喻的變化。換句話說,人心好似一面鏡,當用平淡祥和的心態,去觀察周圍的人或事物時,周圍的人或事物也會用相同的眼光來看待自身。對我來說,看著過去的敬婷,就像詩仙見敬亭山,一幕幕鮮明的意象,仍映入心智想像中,只是逐漸遠去,我們一同生活的美好體驗,及於生活中的每一分、每一秒。 「生日快樂,小美」這句話,我一直不知道該如何再開口,只希望現在有機會能聽進去。眾鳥高飛,孤雲獨去,誰與誰能夠,不離不棄?...

by jserv at June 30, 2008 05:39 AM

June 28, 2008

tsung

June 27, 2008

jserv

用 Makefile 實現 quick sort

在大學課程中,quick sort 大概是用來闡述遞迴概念的最佳範例,因為既簡潔又實用。多數的程式語言也可採用此概念,甚至連 GNU make 裡頭 function call 也能遞迴,所以,何不試著實做 quick sort 呢?以下是 proof-of-concept 的試作品: TRUE = 11111 gt = $(shell if [ $1 -gt $2 ] ; then echo $(TRUE); fi) lt = $(shell if [ $1 -lt $2 ]...

by jserv at June 27, 2008 11:27 PM

Rex's blah blah blah

Java in Firefox Extensions

在追一個 Firefox 延伸模組時,試著玩了一下在 Firefox 外掛中使用 Java 的方法。

原來你可以用 XPConnect 來存取 Java Object,甚至將你的 Java object 封裝成 XPCOM,以方便 Java Script 取用。範例可參考 Simile ProjectJava Firefox Extension。於是乎,你的外掛介面可以用 XUL/Java Script 實做,但後端丟給 Java 來處理,若是拿來整合某些企業應用程式,應該可以比較快速的拉出使用者介面與整合商務邏輯。

或者,你也可以使用 JavaXPCOM,讓你的 Java 程式存取 XPCOM 介面的元件。

by Rex Tsai at June 27, 2008 03:36 PM

jserv

教育訓練:Gtk+ 程式設計初體驗

過去很榮幸得以在不同的場合,與朋友分享過一些電腦技術主題的演講,下個月則嘗試時間較長的教育訓練,但仍維持免費的分享形式。主題是「Gtk+ 程式設計初體驗」,由 [酷學園] 張羅議程的進行,詳細資訊可參考 [公告],以下摘錄部份內容: 簡介 學習 GUI 程式設計,一開始從 "Hello World" 等級程式出發都沒問題,但頗為枯燥,「做中學」的模式較易讓人產生自信。本議程以專案目標導向的形式,探討 [Gtk+] 與相關技術,如: 用 Gtk+ 搭配 GStreamer,打造簡易的 media player 以 Gtk+ 的延伸 widget set,打造個 text editor 透過 Gtk+/WebKit,打造可嵌入到 Gtk+ 應用程式的 Web Browser 最後,我們將可善用開放技術,整合出期望的應用程式 時間:2008 年 7 月 26...

by jserv at June 27, 2008 10:11 AM

June 26, 2008

tsung

Rex's blah blah blah

開源飛信

之前曾經介紹過中國移動的飛信服務,是整合短訊與電腦即時通訊的服務。最近知道有兩個開放原碼計畫分別實做了飛信的協定,一個是 Fetion Pidgin Plugin、另一則是 LibFetion。於是你在 Linux 上,也可以使用飛信來傳訊到手機上了。若是有人實做了 Telepathy project 介面,那就更容易整合到其它不同的通訊軟體上了。

Source: libfetion

不知道台灣電信產業是否有人想作類似的服務,而不是鎖定平台與通訊協定的服務 (中華電信台哥大, 遠傳)。或是讓只能傳送簡訊的低階手機也可使用,且提供合理的費率。(說真的,誰的錢多到想使用這樣的服務?)

by Rex Tsai at June 26, 2008 09:32 AM

Damon

gnome沒有聲音

這幾天把電腦重灌,發覺裝好gnome之後登入沒有聲音,有裝了gnome-audio
這兩天經過jesse大的提醒,發覺再裝gnome這個meta package的時候並不會一併安裝esound,所以只要下這個指令
sudo apt-get install esound
把esound安裝起來就有聲音了

June 26, 2008 07:39 AM

jouston

Ubuntu對自由軟體世界的貢獻

自從2008年3月31日的這篇文章揭露之後,全世界的自由軟體界有了不小的震撼,原來Ubuntu在Linux Kernel上的貢獻比不上她的幾個競爭對手?!這樣的震撼對我來說其實沒有甚麼感覺,直到前幾天在Moblin Road Show 2008被鼎鼎大名的威豆博士踢館才真正感覺的到震撼。(後知後覺?)...

June 26, 2008 05:15 AM

June 25, 2008

Damon

wii台灣專用機即將上市

今天看到的新聞,wii台灣機要上市了,終於在開賣1年半之後要有公司貨了,不過呢,可能是代理商能力不足或是其他的原因,推出的產品不僅功能比水貨差,連中文介面都沒有,只有附上中文說明書...真是令人失望
價格上也沒有差很多,看來只有保固方面稍微有優勢,看來還是買水貨比較實際

June 25, 2008 12:18 PM

Rex's blah blah blah

Adobe AIR for Linux

今年三月底時,Adobe 在 Adobe Lab 發行Adobe AIR for Linux alpha 版本。Adobe AIR 是一種執行環境,提供一個可使用 Adobe Flash, Adobe Flex, HTMLAjax 開發桌面 RIA 應用程式的平台。

試玩了一下,可以安裝 twhirl (Running Twhirl on Ubuntu 7.10) 等軟體沒有問題。可惜的是,目前 Linux 版本還不能支援 XIM,以至於無法輸入中文。

另外一個惱人問題是 Adobe AIR 將 zip 格式檔案都以 xdg-mime (xdg-mime of Portland project) 註冊成使用 Adobe AIR 開啟,以至於你的 zip 檔、OpenOffice 文件檔 (也是 zip 壓縮格式) 都變成以 Adobe AIR 開啟了!

解決辦法是

先移除原本的 xdg-mime 設定

# xdg-mime uninstall –novendor “/opt/Adobe AIR/Versions/1.0/support/AdobeAIR.xml”

以編輯器開啟 “/opt/Adobe AIR/Versions/1.0/support/AdobeAIR.xml”,並移除檔案中以下文字

<magic priority=”100″>
<match type=”string” value=”PK\003\004″ offset=”0″ />
</magic> 

重新安裝 xgd-mime 設定

# xdg-mime install –novendor “/opt/Adobe AIR/Versions/1.0/support/AdobeAIR.xml”

上述 # 開頭指令,指使用 root 執行。

by Rex Tsai at June 25, 2008 09:25 AM

jserv

探訪 stack frame:談不定數量參數

前文 [以 C 語言實做 Functional Language 的 Currying] 已探討在 IA32 stack 的操作,讓 Currying 的行為得以在此基礎,予以實現,而我們還可看另一種應用:C 語言的不定數量參數,也就是 stdarg.h 裡規範的行為。當我們使用 printf() 函式搭配強大的資料格式化處理 (printf 本身就是個小型的 interpreter) 時,不免會其運作行為感到好奇,以下是 GNU/Linux 上 /usr/include/stdio.h 的 prototype:(取自 glibc) __BEGIN_NAMESPACE_STD ... /* Write formatted output to stdout. This function is...

by jserv at June 25, 2008 05:33 AM

June 24, 2008

Damon

新專輯發表

這個月讓我有興趣的兩張新專輯,分別是
alanis morissetts的新專輯Flavors Of Entanglement
image
cold play的Viva La Vida
image
每次聽alanis morissetts的音樂都會有不同的感受,相較之下,coldplay這張個人用kkbox試聽之後覺得只是普通而已
這兩張kkbox上面都有完整的專輯可以聽,避免買到地雷

June 24, 2008 01:39 PM

dken

Firefox 愈來愈普及了!

台灣也吹Firefox 3熱 社群官網被塞爆 Firefox 愈來愈普及了,但是我們公司就是硬要鎖 Firefox...

More...

by noreply@blogger.com (dken) at June 24, 2008 01:13 AM

June 23, 2008

huki

讓Linux下Gvim也可以用"Edit with existing Vim"

今天看到$4大的文章:help new-vim-server
果然是好物啊!
發現了原來在win32時用gvim的好功能
只是之前自己一直沒有用心去看help
多虧$4大的文章提醒了我
現在也可以把他做出來了
其實大家在command line底下打上
[huki@pc-huki ~]$ gvim --help
VIM - Vi IMproved 7.1 (2007 May 12, compiled May  4 2008 19:28:36)
..............................
...(繼續閱讀)

June 23, 2008 08:26 AM

June 20, 2008

Asho(阿信)

節約,省電的好幫手:Cpufrequtils

最近常聽到節約,省電的口號,加上七月份電費要開始上漲,省電變成每台電腦的基本功能。

今天要介紹的就是要讓您的CPU降速、降溫度的好工具:cpufrequtils。

在kernel-2.6中,已經實作了動態調整CPU clock的kernel module:cpufreq,它支援Intel/AMD的CPU,小弟的CPU是Althon Dual Core 3600+,支援CnQ,在待機時可以降下速度,溫度也會降低。

首先,先安裝適當的module,以AMD的CPU而言,採用的是powernow-k8:
modprobe powernow-k8
modprobe cpufreq_ondemand

以及相關的cpufreq module,小弟採用的是ondemand模式,接下來,請安裝cpufrequitls,修改
/etc/default/cpufrequtils

加入
ENABLE="true"
GOVERNOR="ondemand"
MAX_SPEED=1900M
MIN_SPEED=1000M

或者直接修改/etc/init.d/cpufrequtils,內容如上。重新啟動cpufrequtils
/etc/init.d/cpufrequtils restart

執行cpufreq-info

analyzing CPU 0:
driver: powernow-k8
CPUs which need to switch frequency at the same time: 0 1
hardware limits: 1000 MHz - 1.90 GHz
available frequency steps: 1.90 GHz, 1.80 GHz, 1000 MHz
available cpufreq governors: powersave, conservative, userspace, ondemand, performance
current policy: frequency should be within 1000 MHz and 1.90 GHz.
The governor "ondemand" may decide which speed to use
within this range.
current CPU frequency is 1000 MHz.

出現上述字樣就表示cpufreq已經設定成功,檢查/proc/cpuinfo,您就會發現CPU的頻率會在1G~1.9G跳動,剩下的,就是好好享受cpufreq帶給你的便利性了. :-D

PS: cpufreq支援多種policy:
performance: 全速
powersave: 以最省電的方式調整CPU clock,大部份都在最低的頻率
ondemand: 依照CPU loading的程度動態調整,撥SD/HD的影片時,會跳動的最明顯。


PS2: 還有另一套cpufreqd,它是以daemon的方式運作,設定的內容更細,還能依照ACPI來監控電池容量改變CPU頻率,由於弟只有桌上型PC,所以cpufrequtils簡單的設定方法已經符合弟的需求了。

by 阿信 (noreply@blogger.com) at June 20, 2008 08:32 PM

jserv

操作 X 的 Cut and Paste Buffer

在 X Window System 要處理 X client 之間的資料分享,因為設計本質上與傳統 GUI 有極大差異,所以,不可等閒視之,也就是說,在 Win32 下很普通的 Clipboard 處理,搬到 X 下,其實得考慮相當多。Win32 Clipboard 無法「直接」對應到 X Clipboard,我們必須分很多層級去思考,一般的 X client 中,以滑鼠(mouse) / 指標(pointer) 作區域的文字 / 物件選擇動作,在真正貼上或複製到標的視窗前,其實涉及到跨越實體環境的資料分享 (考慮到 X Protocol 分散式處理本質) 的議題,所以,光是如何保存這些中間資訊,就是很大的學問。 簡單的文字,可透過名為 X cut buffer 的空間,暫時保存 X cut-paste...

by jserv at June 20, 2008 04:11 PM

June 19, 2008

jserv

開機見 Hello World

幾周前,c9s 寫了篇文章 [如何在 Linux 下使用 GNU AS 撰寫組合語言(1)],找筆者協助檢閱,簡單扼要地提及 ELF 執行檔主體、GNU Assembler 語法,最後以 80486 以後 (含) 引入的 cpuid 指令作範例,是不錯的入門文章。閱讀時,也想到之前提過 [電子書《使用開源軟件-自己動手寫操作系統》免費下載],這份來自對岸高手 [solrex] 的電子書籍,於是,筆者也提供一個具體而微的組合語言範例,使其置入 floppy / hard-disk 的 boot sector 中,能如同 boot loader 一般,當系統啟動時,就被載入執行。 當然,這裡還是用筆者最愛的 "Hello World" 程式,用組合語言來實現如下: .text .globl start .code16 start:...

by jserv at June 19, 2008 06:55 PM

FourDollars

:help new-vim-server

其實早在 Vim 6.X 的時候就有的一個功能
在 Ubuntu 8.04 上面要裝上 gvim 才能夠使用
就是先執行一個 vim 來當 server
vim --servername VIM file1.txt
然後再執行
vim --remote-tab file2.txt
就可以把 file2.txt 開個 tab 在前面那個 vim-server 裡面了~
詳細的說明可以參考 :help new-vim-server

by FourDollars (noreply@blogger.com) at June 19, 2008 12:04 PM

:help new-vimgrep

Vim 7.X 有一個相當實用的功能 vimgrep
相關的說明可以參考 :help new-vimgrep
我自己則是定義了三個快速鍵來使用
nmap  viwy::vimgrep /\"\>/ **/*.[ch] **/*.[ch]pp **/*.java **/*.pl **/*.rb **/*.py
nmap :cn
nmap :cp
這樣就可以很方便地在 C/C++/Java/Perl/Ruby/Python 的程式碼樹當中快速搜尋關鍵字~
使用 Ctrl+n 來跳到後一個出現的地方
使用 Ctrl+p 來跳到前一個出現的地方
連 Google Search 都沒有這麼好用~ :P

by FourDollars (noreply@blogger.com) at June 19, 2008 11:55 AM

jserv

窺探 .bss section

幾年前只是對系統設計感到困惑,沒想到「分析 GCC 對 Hello World 的重重布幕」一類的舉動,竟成為激勵自我成長的目標,實在始料未及。拜 C 語言這種「披著高階語言羊皮的低階語言之狼」所賜,我們可透過稍早 blog [自我印列 ELF 簽名] 所提及的途徑,探索記憶體位址背後的意義。同樣地,我們也可從實驗觀察 GNU/Linux 中 ELF (executable and linkable format) 格式執行檔裡頭 .bss section 的呈現,關於這部份的背景知識,可參閱 Jollen 整理的 [.bss section:C 語言所種下的因] 與 [BSS Section 觀念教學] 等文章,本文則針對「窺探」的手法作補充。 「窺探」ELF 執行檔有許多途徑,我們當然可用 binutils 裡面的 readelf /...

by jserv at June 19, 2008 09:33 AM

Rex's blah blah blah

Reddit 開源了

哇,若你是個 Geek, 而且對 Linux, Python, Open Source Software 感興趣,你大約已經常常閱覽 Reddit.com,Reddit 是一個 Social bookmark 網站,使用族群較為偏熟悉技術的工程師。

就像所有的 Social Bookmark 一樣,首頁的排序與計算方式總是受到質疑與挑戰。於是 Reddit 乾脆就把整個網站的程式碼開放原碼,於是所有人都可以看到演算法與修改,也可以回饋建議、甚至 Patch。程式碼可於 code.reddit.com 下載。目前 Reddit 用的其他開放原始碼軟體還包含 Debian, lighttpd, HAProxy, PostgreSQL, Slony-I, 數個 Python libraries, Psychopg, pylons, Solr, Tomcat, Ganglia, Mercurial, Git, gettext, daemontoolsmemcached 等。

於是,好事者再也沒有理由質疑 Reddit 動了手腳。

reddit goes open source: message from the alien mascot

by Rex Tsai at June 19, 2008 07:16 AM

June 18, 2008

jserv

以 C 語言實做 Functional Language 的 Currying

在電腦科學的領域,Functional Language 的 Currying (也譯作「Curry 化」) 的正規定義為:(出自 [Wikipeida]) 「把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,並且返回接受餘下的參數而且返回結果的新函數的技術。 此技術的命名係紀念 Christopher Strachey 以邏輯學家 Haskell B. Curry (1900-1982,師法自數學家 David Hilbert,Haskell Funcational Language 也是以他命名),由 Moses Schönfinkel 和 Gottlob Frege 兩位所提出。本文試著以 C 語言模擬出 Currying 的特性,語法層面較為接近 Lisp 與 Prolog,為避免與 C 語言程序性思維的 function (函式) 用語混淆,當談及...

by jserv at June 18, 2008 06:55 PM

Rex's blah blah blah

Software sucks

大約任何一個軟體開發者都可能碰到詭異的 undocument API 、噁爛的架構,或者碰到設計有問題的硬體,大約都會情不自盡的爆粗口。偶爾,你甚至會被其他莫名其妙的開發者惹火,例如未充分溝通就擅改程式碼包成套件的情境。

前些時候,quodlibet 的 Debian 套件維護者 Sebastian Dröge 因為誤解了 quodlibet 所使用 GStreamer 中的一個 API 相容問題,於是直接擅改程式碼中的一段,以便可以於新版的 GStreamer 中使用。但是這樣的行為卻未事前於 quodlibet 開發者 Joe Wreschnig 溝通,而那其實算是 GStreamer 的問題,並非 quodlibet 的錯誤。

於是,Joe Wreschnig 惱怒之下,身為一個上游開發者,就在 quodlibet 中也改了一段因應 GStreamer API 更改的措施。而且順便戳了 Sebastian Dröge 一下,要他去死一死吧。於是身為一個 Debian Developer,自然的解決方式當然是發一個 Bug Report。而且解決的討論很自然就往 DFSGDebian Policy 發展。所幸,最後 Tristan Seligmann 另外改了程式碼,並做了一份新的壓縮檔,算是解決了這個幼稚問題。

有趣的是 Joey Hess 在討論中,順便彙整了過去 Debian 修改紀錄中,曾經出現的粗口表,非常好笑,只能說 Software 真是 Sucks。XD

另外一個好玩的研究是 Vidar Holen 研究了 Linux 核心中有多少詛咒粗口,Linux kernel swear counts。我們可以拿程式碼中的髒話平均數量當作判斷品質的一個參考值嗎? :-p

by Rex Tsai at June 18, 2008 05:30 AM

June 17, 2008

Asho(阿信)

mhddfs: join several real filesystems together to form a single larger one

FYI
http://debaday.debian.net/2008/05/25/mhddfs-join-several-real-filesystems-together-to-form-a-single-larger-one/

該軟體的是利用FUSE(User space filesystem)這個module將多顆硬碟串成一個virtual device,而非像已往的Raid,LVM的方式,

他寫入的機制很簡單,假設有三顆硬碟:A,B,C。當寫入資料時,若資料大於A硬碟所餘的大小,就會換到第二顆。同理,第三顆硬碟的操作也是如此。

另外,當它寫入第一顆時,發現還有空間太小必須換另一顆硬碟時,會搬移剛剛寫入的資料到接續有足夠大小的硬碟。

雖然機制上沒有Raid, LVM那麼有效率和安全,但不失為一個單機版合拼硬碟的方法。

目前Debian testing/unstable已經有,Ubuntu尚未納入,參考看看

by 阿信 (noreply@blogger.com) at June 17, 2008 11:41 PM

Rex's blah blah blah

就是現在!一起來破世界紀錄!

Firefox 3 正式發行了!快去下載吧!

新版的 Firefox 速度比 Firefox 2 快上好幾倍,由於使用了新的 PGO 編譯技術以及新的 XPCOM Cycle Collector 實做,因此系統不會莫名的吃掉好幾倍的記憶體,以至於行為緩慢。同時在介面上也做了眾多的改善,包含新的「收藏庫」可以用以瀏覽歷史與書籤管理、書籤功能則大幅改善操作方式,並新增了標籤功能、新的下載介面、外掛程式介面、與安全保護機制,終端使用者在瀏覽可能有惡意軟體的頁面時,也會被警告,避免無意瀏覽或下載有病毒的網頁。

諸多的新功能不彷參考 Firefox 3 預覽 (1) Firefox 3 預覽 (2)。或者參考 Mike Beltzner新功能簡介:

無論你是否曾經用過 Firefox, 現在都該立即試一試,快到網站上下載!成為破當日下載次數世界紀錄的一員!

by Rex Tsai at June 17, 2008 05:19 PM

dken

tsung

June 16, 2008

Rex's blah blah blah

為什麼不應作原生套件呢?

Debian 的軟體套件原始碼通常包含幾個檔案,分別是 dsc, diff.gz 與 orig.tar.gz.

.dsc 是一個文字檔,包含軟體的基本資訊、如版本、維護者資訊與原始碼檔名與驗證碼 (checksums) 資訊 。.diff.gz 是壓縮過後的差異檔,由於軟體套件都必須針對不同的套件系統進行調整,以便符合套件系統的規矩。而 Debian 的方式是保留由上游所發行的原始碼壓縮檔,也就是 .orig.tar.gz 檔案,並將所有的修改另外儲存於 .diff.gz 檔,包含 Debian 包裝軟體時特有的 debian/* 檔案。

於是,對於使用者/原開發者而言,可以清楚的分辨哪些碼是被 Debian 軟體套件維護者所修改,在除錯或維護上都可以比較清楚的區分。若想了解 Debian 包裝軟體的細節不妨參考我的 Debianziation HOWTO

至於所有原生套件與非原生的套件的差別,則在於是否有 .diff 檔案。若你所包裝的軟體原始碼中本來就含有所有 Debian 所需要的 debian/rules, debian/* 檔案,你在產生 .deb 安裝檔時,套件包裝軟體就不會/無法生成差異檔,而只會生成 .tar.gz 檔案。

通常包裝成原生軟體套件 (Native Package) 的狀況是維護者手誤所造成,大約是忘記將原始檔名改成正確的 .orig.tar.gz 名稱。但有些時候,是軟體套件維護者刻意製成。但是除非該套件是針對 Debian 所開發,不可能被移植到其他套件系統上,否則不應該包裝成原生套件。

有些開發者原本就使用 Debian 作為開發平台,偶爾為了方便也會直接在發行的壓縮檔案中置入 debian/* 檔案。但是這是不應該的,Debian Mentors FAQ 裡面有稍加解釋,事實上在原始檔壓縮檔中放入 debian/* 檔案,很容易造成誤解與困擾,特別是需要追蹤修改紀錄的狀況。另外還有如下的原因

  1. 其他套件系統沒有理由想要、需要 Debian 的特定東西。
  2. 所有為 Debian 所作的的修改,都會造成一次版本提交。結果莫名的影響其他套件系統都需要更新升級。
  3. 不只是 Debian 使用 debian/,其他延伸套件系統可能也需要修改其中檔案才能運作。否則要則他們必須修改原本的原始碼壓縮檔,或者以一個 patch 來修正你的 debian/ 檔案。
  4. 當有安全問題或其他因素需要作 NMUs 時,這個 debian 目錄會造成其他人難以維護追蹤的困擾。

與 Debian Developer 討論之得。

by Rex Tsai at June 16, 2008 11:49 AM

June 15, 2008

kanru

Evince Autoreload

Evince 是個好用的文件瀏覽器,速度非常的快,是我平時最常用的 PDF 瀏覽器。有時候在編輯文件就會希望可以在轉成 PDF 之後,可以直接更新 Evince 內容。上網搜尋了一下,不只我有這樣的需求,而且已經有 patch 了,這個熱騰騰的 patch 是 6/12 才更新的。

http://bugzilla.gnome.org/show_bug.cgi?id=304249

by kanru at June 15, 2008 06:13 AM

June 14, 2008

tsung

June 13, 2008

tsung

dken

Plurk 一目暸然的條列式訊息

從 Twitter 轉到 Plurk 幾天了吧,從第一天使用開始,映入眼簾的一第一幕就是時間軸,和訊息的呈現方式,Plurk...

More...

by noreply@blogger.com (dken) at June 13, 2008 04:17 AM

June 09, 2008

Rex's blah blah blah

Linux Hater

還記得我寫過一篇「來亂者,去死!!」,詳細分析過戳樂 (Troller)。這裡有一個典型的 blog, Linux Hater’s Blog,言詞辛辣、諷刺,有些論點我無法同意,有些則犀利的點出問題。

如果你對 Linux 的各方面軟體開發、應用、文化,都具備一定程度的認知。你讀起此部落格肯定就像是讀幽默短文一樣哈哈大笑 (但別過度反應了,這可以算 Slashdot 上的長篇版機車留言)。

以下幾篇是我個人覺得夠諷刺,或值得思考的議題。

如果你要當一個 Troller, 至少也試著寫些具備觀點的文章。當個直言的真小人,比言之無物的偽君子實在來著有格調多了。

by Rex Tsai at June 09, 2008 02:21 PM

June 07, 2008

Cornelius

Easytag 2.1.5


以編輯 Mp3 Tag 來說,我覺得最好用、最 Powerful 的工具就是 Easytag 了,但在 Windows 下也找不到比他好用的軟體。

前一陣子一直遇到 Tag 改完之後寫入,用 Rhythmbox 讀卻無法讀出的問題,弄了許久都無法修正好。另外 Easytag 2.1.4 有一個 Bug 就是你如果選擇多個檔案,然後選 Settings -> Preference ,Easytag 就會掛掉。 XD

於是上官網抓了最新的 2.1.5 來用,沒想到問題迎刃而解。

以下是方便以後重編的 Script:
#!/bin/bash
mkdir tmp
cd tmp
pkg_name=easytag-2.1.5
wget -c http://nchc.dl.sourceforge.net/sourceforge/easytag/$pkg_name.tar.bz2
tar xvf $pkg_name.tar.bz2
cd $pkg_name
sudo apt-get -y build-dep easytag
sudo apt-get -y install libid3-3.8.3-dev libogg-dev libflac-dev libflac++-dev libmp4v2-dev libmp4v2-0 libwavpack-dev gettext
sudo apt-get -y install libgmp3-dev libvorbis0a libvorbis-dev libogg0 libogg-dev
sudo apt-get -y install libfaad-dev libfaad2-0 libmp4v2-dev libfaad2-0 libmp4v2-0
sudo apt-get -y install libid3tag0 libid3tag0-dev libspeex-dev
./configure
make
sudo make install

by Cornelius (c9s) (noreply@blogger.com) at June 07, 2008 10:53 AM

June 06, 2008

Cornelius

在 Linux 下使用 GNU AS 編寫組合語言 - 使用 gdb 進行除錯

日前有寫一篇『在 Linux 下使用 GNU AS 編寫組合語言』,現在以 cpuid 的範例來示範如何使用 gdb 除錯。

首先我們在組譯的時候,需加上 -gstabs 參數,as 會將除錯所需要的資訊編進去,以便 gdb 除錯。
[ cpuid:c9s-desktop : 19:05:43 ] $ as -gstabs -o cpuid.o cpuid.s
[ cpuid:c9s-desktop : 19:05:58 ] $ ld -o cpuid cpuid.o
除錯,只需要將連結完的執行檔丟給 gdb 即可:
[ cpuid:c9s-desktop : 19:06:04 ] $ gdb cpuid
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb)
這樣就進入 gdb 了。

接下來我們可以在 _start 標籤之位址插入中斷點,然後將此程式執行,程式應在 _start 中斷
(gdb) break *_start
Breakpoint 1 at 0x8048074: file cpuid.s, line 7.
(gdb) run
Starting program: /home/src/asm-code/cpuid/cpuid
The processor Vendor ID is 'GenuineIntel'

Program exited normally.
(gdb) quit
怎麼回事,中斷點無效了?這是 gdb 一個 Bug,他把一開始的中斷點_start忽略了。XD

經過測試發現似乎是在一開始的第一個指令中斷點會無法作用?解法是,在 _start 後加入一個 nop 指令。nop 指令並沒有功能,他不做任何事情。
.globl _start
_start:
nop
movl $0, %eax
cpuid
movl $output,%edi
movl %ebx, 28(%edi)
接下來重新組譯後,使用 gdb 除錯:
(gdb) break *_start+1
Breakpoint 1 at 0x8048075: file cpuid.s, line 8.
(gdb) run
Starting program: /home/src/asm-code/cpuid/cpuid

Breakpoint 1, _start () at cpuid.s:8
8 movl $0, %eax
Current language: auto; currently asm
因為 nop 只有一個 byte ,我們將中斷點設置在 _start 位址後的一個 byte ,就會停在中斷點了。

接著你可使用 s 或 n 來作單步執行。 (s for step , n for next )

gdb 的基本指令:
info registers顯示所有暫存器內容
print印出特定暫存器或者變數的值
x印出特定記憶體位置的內容

print 可搭配不同的修飾符來選擇以何種格式印出 ( print/d 印出十進位數值 , print/t 印出二進位數值 , print/x 印出十六進制數值 )

此外 x 指令也可搭配修飾符來選擇格式

x/nyz
  • n 代表要印出幾個欄位 ( 1 , 2 , 3 ... )
  • y 為輸出格式,可為 c (字元) , d (十進制) , x (十六進制)
  • z 為大小
其中 z 可為:
  • b 為 byte
  • h 為 16 bit word (halt-word)
  • w 為 32 bit word
譬如:
(gdb) x/42xb *_start
0x8048074 _start>: 0x90 0xb8 0x00 0x00 0x00 0x00 0x0f 0xa2
0x804807c _start+8>: 0xbf 0xac 0x90 0x04 0x08 0x89 0x5f 0x1c
0x8048084 _start+16>: 0x89 0x4f 0x24 0xb8 0x04 0x00 0x00 0x00
0x804808c _start+24>: 0xbb 0x01 0x00 0x00 0x00 0xb9 0xac 0x90
0x8048094 _start+32>: 0x04 0x08 0xba 0x2a 0x00 0x00 0x00 0xcd
0x804809c _start+40>: 0x80 0xb8

(gdb) print/x $ebx
$1 = 0x756e6547

(gdb)
其中 x/42xb 代表印出 _start 標籤開始之後的 42 個 Byte ,並以 16 進制印出。 print/x 代表以 16 進制印出。 print/d 以十進制,print/t 以二進制。

以上簡略介紹至此。

by Cornelius (c9s) (noreply@blogger.com) at June 06, 2008 08:10 PM

June 05, 2008

Rex's blah blah blah

Native ezPeer for linux

順便提一下排名第二的音樂下載軟體 - ezPeer+。話說 ezPeer+ 其實為了 Linux 平台開了一版介面 ezPeer+ for Linux 1.0,是使用 XULRunnermplayer 等軟體元件開發。

後端直接呼叫 mplayer 接取線上串流,會同時執行前端介面與後端播放軟體。偶爾會因為軟體處理不當,造成使用者按下暫停時,系統依然於背景播放音樂。稍微有點惱人的小問題。介面上也未提供進階選項,如調整快取大小等,我在 Seednet 上聽取音樂有點停頓。

此外大約是為了 mplayer 拿掉了 Windows Media DRM 功能,目前並沒有提供下載的功能,只能聽線上串流音樂,不過這應該已經可以滿足很多想在 Linux 上享受音樂的朋友。

可惜的是 ezPeer+ for Linux 目前只提供給 ASUS EeePC 的使用者使用,並未提供下載。若你購買了 EeePC,其實可以透過 dpkg-repack 重新將程式包成 .deb 檔案後丟到其他的 Debian/Ubuntu 上執行。

我說,你們這些多媒體娛樂資訊商,快照顧照顧我們卑微的 Linux/Unix 使用者吧。

by Rex Tsai at June 05, 2008 07:07 AM

在 Linux 上執行 KKBOX

上次用 Wine 1.0-rc1 測試了一下 KKBOX,由於上次測試時使用 Wine 實做的 ShDocVwMsHtml 等元件。由於無法透過內嵌的網頁登入,因此大部份某些功能無法順利使用。

但你若先將 Microsoft Media Player 與 Microsoft Internet Explorer 裝進 Wine 中,就可以順利執行起 KKBOX 了!安裝過的過程十分繁複,因此我其實是透過 wine-doorsIEs4Linux 才安裝成功。由於 IEs4Linux 預設會安裝一個獨立的 wine 系統,並把軟體預設安裝 $HOME/.ies4linux,因此必須稍加修改 IEs4Linux,以便強迫它安裝到正確的 wine 目錄。然後再重新安裝執行一次 KKBOX 即可成功啟動啦。

使用狀況倒是沒有甚麼問題,可聽取線上串流,離線下載由於尚未購買月卡,還無法測試。目前的一點點小問題是,左邊的選單還是亂碼,一般下拉式選單倒是沒有問題。此外嵌於軟體首頁的 Flash-based MV 會有嚴重閃爍的問題。

這是在 wine 1.0-rc1 與 wine 1.0-rc2 上測試。待有善心人士整理 Step by Step HOWTO. 或者乾脆整理成單鍵安裝程式吧。

by Rex Tsai at June 05, 2008 05:57 AM

June 04, 2008

huki

[分享] GHunter v 0.0.3 - 專看漫畫的看圖程式

好久沒更新了,最近去到新公司正努力的被操(好開心吶~~學了不少)
GHunter,一套取名純粹kuso的看漫畫的看圖程式
hunter 261復刊,現在已經27X了吶,原來我也會拖稿
哈哈~~~~
從看了pcman大大的XD Programming之後
就在練習用glade寫一個看圖程式
玩玩~~~
後來看到pcman大的gpicview程式
真的很不錯
不過和我看漫畫的習慣不順手
...(繼續閱讀)

June 04, 2008 03:47 AM

yungyuc

Hg WinMerge

重灌了 XP,拿掉了 TortoiseHg,又拿掉了 TortoiseSVN。

... continue...

by yyc@seety.org (yungyuc) at June 04, 2008 03:18 AM

June 03, 2008

Cornelius

如何在 Linux 下使用 GNU AS 撰寫組合語言(1)

在 DOS 下寫組合語言有 MASM 組譯器,那麼在 Linux 下呢?我們有 GAS (GNU AS) 以及 NASM 等等。

NASM 一開始是為商用軟體為導向而開發的,但最近已經為開放原始碼釋出。NASM 支援 Windows 以及 UNIX 環境,能夠產生 UNIX , 16-bit MS-DOS , 32-bit Windows 格式的執行檔。

GAS 是由 GNU 所開發的自由軟體,在 UNIX 上是最受歡迎的跨平台組譯器。基本上組譯器都是針對特定處理器所設計的,但 GAS 特別之處在於他支援多種處理器,可產生不同種處理器的指令碼( instruction code ),通常 GAS 能夠自動的偵測硬體平台並產生相對應的指令碼。關於 GNU AS 所支援之處理器可參考 gas Manual ( Machine-Dependencies )

當然不同組譯器,語法也都不相同,NASM 和 GAS 語法是有差異的,稍後會說明。在此我們選擇 GAS 為組譯工具。

如何在 Linux 底下使用 gas 撰寫組合語言呢?首先,必須先安裝 binutils 這個套件,若你是在 Debian 或 Ubuntu 底下可透過 apt 安裝:

sudo apt-get install binutils

若沒有,可於 GNU 官方網站(http://ftp.gnu.org/gnu/binutils/)取得程式碼,解壓縮之後編譯,安裝他

./configure
make
make install


binutils 套件除了有 GNU as 之外,還有其他工具如:addr2line ar c++filt gprof nlmconv nm objcopy objdump 等等,可參考此說明(中華民國軟體自由協會),或者參考 GNU 官方文件 binutils 的說明

一支以 GAS 為組譯器之程式的基本架構如下:
.section .data
# 已初始化的資料

.section .bss
# 未初始化的資料

.section .text
.globl _start
_start:
# 程式碼由此開始
其中 .data 區塊,為放置初始化資料區塊,也就是變數已經有了初始值。.bss 則為未初始化資料區塊,此區塊為非必要。.text 則為程式碼區塊。 _start 為程式一開始的進入點,在 Linking 的時候會自動找到 _start 這個標籤為進入點,若是沒有 _start 標籤的話,Linking 時會出現以下訊息:

$ ld -o test test.o
ld: warning: cannot find entry symbol _start; defaulting to xxxxxxx


對於 GNU AS 所使用的語法在此針對幾點說明:

GAS 的原開發者選擇實做 AT&T opcode 語法作為此編譯器之語法,是因為 AT&T opcode 語法是由 AT&T Bell Labs 所發展,在當時是為那些實做 UNIX 系統的處理器而設計的。

也因此以 GNU AS 來撰寫 Intel 平台的組合語言程式是比較令人容易混淆。

有幾點差異如下:
  • 立即定址( immediate operands) 使用 $ 符號作為前綴,譬如說要使用數值 4 作為值,則寫作 $4。
  • 暫存器名稱一律使用 % 作為前綴,譬如說 EAX 則寫做 %EAX
  • 來源與目的之運算元位置與 Intel 語法不同之在於,AT&T 之來源運算元在前面,目的運算元在後。譬如將十進位數字 3 放入 EAX 暫存器,AT&T 寫作 movl $3, %eax ,Intel 寫法則寫為 mov eax, 3。
  • 為表示資料位址,AT&T 語法寫做 movl $test, %eax ,Intel 語法則為 mov eax, dword ptr test。
  • 跳躍或者呼叫使用不同的語法來定義區段(segment)以及偏移量(offset values),AT&T 使用 ljmp $section , $offset 而 Intel 使用 jmp section:offset。
如想知道的更清楚,這裡有一篇文章討論 NASM 與 GAS 之差異 (Linux assemblers: A comparison of GAS and NASM)

先寫一個最基本的小程式,此範例為一程式之最基本的架構,在此以 cpuid 為範例:
# cpuid.s Sample program to extract the processor Vendor ID

.section .data
output:
.ascii "The processor vendor id is 'xxxxxxxxxxxx''\n"
.section .text
.global _start
_start:
movl $0,%eax
cpuid

movl $output,%edi
movl %ebx, 28(%edi)
movl %edx, 32(%edi)
movl %ecx, 36(%edi)

movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $42, %edx
int $0x80

movl $1,%eax
movl $0,%ebx
int $0x80
接下來做大略的解說,為示範整個編寫程式的流程,在此不闡述太多細節。第一段
.section .data
output:
.ascii "The processor vendor id is 'xxxxxxxxxxxx''\n"
在資料區塊裡頭宣告一個名為 output 的字串變數。
 movl $0,%eax
cpuid
movl $output,%edi
movl %ebx, 28(%edi)
movl %edx, 32(%edi)
movl %ecx, 36(%edi)
其中第一行, movl $0, %eax 將 0 移至 EAX 暫存器,執行 cpuid 時,會判斷 EAX 的內容取得相對資料。EAX 為 0 時,cpuid 是取得廠商之 ID,譬如說 Intel , Geniue 等等,cpuid 執行後,會將資料分別放入 EBX , EDX , ECX 。第 3 行,將 output 字串之起始位址存至 EDI 暫存器 ( EDI 暫存器是用來存放操作目的字串指標之暫存器 ),接著將 EBX,EDX,ECX 裡面存放之結果字串放入 EDI 暫存器指向之位址加上偏移量的位置內。
movl %ebx, 28(%edi)
此行代表將 %ebx 內四個 Byte 之內容搬移到 EDI 存放之位址 + 28 Bytes 之位址,其 28 剛好是 xxxxxxxxxxxx 之起始的位址。因此 28,32,36 這三行搬移指令剛好將 12 個 x 補滿。

現在我們有等待輸出的字串了,接下來要做的事情就是要將字串印出來。
 movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $42, %edx
int $0x80
這五行為執行系統呼叫 ( 何謂系統呼叫?可參見此 ),其中 EAX 存放系統呼叫之值,EBX 存放要寫入之檔案敘述元 (STDOUT),ECX 存放字串起始位址,EDX 存放字串的長度。其等同於 write() 系統呼叫。關於系統呼叫,可以在以下定義的檔案找到:

/usr/include/asm/unistd.h

譬如說上頭使用的 write 可以在裡頭找到這麼一行:

#define __NR_write 4

4 就是這麼來的。(其他系統呼叫可參考 System Call Table)

最後以 0x80 之值執行軟體中斷。( Kernel System Call )
 movl $1,%eax
movl $0,%ebx
int $0x80
這三行等同於 exit(0) 系統呼叫。傳回 0 作為程式執行結果。

輸入以下命令,組譯

$ as -o cpuid.o cpuid.s

執行 Linking 的動作 (在此就不闡述何謂組譯以及連結,可參考 System Software )

$ ld -o cpuid cpuid.o

最後便可以執行了。

./cpuid

[1] gas 官方文件
[2] System Software / Beck

by Cornelius (c9s) (noreply@blogger.com) at June 03, 2008 03:43 PM

June 02, 2008

Cornelius

aMule 是很讚的


經過調校後速度也可以很快!
#!/bin/bash
apt-get build-dep amule

cd /tmp
wget -nv -c http://www.hirnriss.net/?area=cvs -O tmpfile
URL='http://www.hirnriss.net/'`g