2007年10月29日 星期一

Vim Tip: 識別子補齊 (Word Completion)

用IDE寫過程式的人,應該都體會過識別子補齊的功能。譬如說,忘記某一結構的某一成員的全名,通常只要記得幾個字母,IDE便會秀出一個符合這幾個字母的小方塊,以供您選擇。

Vim當然有此功能,在Insert mode,把游標移到識別子上,再按Ctrl+nCtrl+p就可以了。

範例

下圖在某一結構詢問有哪些成員。

1

按Ctrl+n變出現下圖之結果:

2

當然忘記某一函式也行。例如,打mem然後再按Ctrl+n,如下兩圖所示:

3

4


[Reference]
Vim官網

2007年10月24日 星期三

Adrian's Blog被LinuxByExample收錄?

剛剛去LinuxByExample逛了一下,發現小弟的Blog被該網站收錄至"Chinese Linux Blog",大驚!!!

升級Ubuntu 7.10 (Gusty)後,Gvim亂碼!

最近把Ubuntu升級至7.10 (Gusty),發現執行Gvim居然會亂碼,囧rz..且還有Assertion。
** (gvim:9348): CRITICAL **: ascii_glyph_table_init: assertion `gui.ascii_glyphs->num_glyphs == sizeof(ascii_chars)' failed
結果是Gvim默認的一些字型(Ex: Sans, Monspace) 搞的鬼。因此換別的字型就可以用了,編輯~/.vimrc加入下列幾行:
if has("gui")
    set guifont=Bitstream\ Vera\ Sans\ Mono\ 12
endif

2007年10月22日 星期一

輕輕鬆鬆升級Ubuntu (7.04 -> 7.10)

今天在網路上看到四元兄有關升級Ubuntu的圖文說明,簡單明瞭,推啊。重點是完全不用修改/etc/apt/sources.list,推薦給大家!!!

2007年10月19日 星期五

ICOS/COSCUP 2007

一年一度的台灣開放源碼研討會將於2007 11月1日至11月4日 (ICOS 2007)在國科會科技大樓舉行,其中較有興趣的是嵌入式系統與驅動程式相關議題,打算衝三天的session,想聽的session如下:

11/2 10:30~11:20 Keynote:自由軟體與商業軟體的對話
11/2 11:30~12:10 Keynote:SUN Microsystems
11/2 13:00~18:00 Linux平台周邊驅動程式開發研討會

11/3 10:00~12:00 COSCUP: 文字資訊處理
11/3 13:00~16:10 COSCUP: Web Based Platform & COSCUP: Distributed Computing
11/3 16:30~18:00 COSCUP: linux based laptop 與社群 & COSCUP: lightning talk

11/4 09:10~10:40 COSCUP: 開放組織新人秀
11/4 10:50~12:00 COSCUP: BSD
11/4 13:00-15:00 COSCUP: 嵌入式系統 #1
11/4 15:20-17:20 COSCUP: 嵌入式系統 #2

2007年10月18日 星期四

Linux Kernel: 強大又好用的list_head結構

程式設計者在設計一個doubly linked list時,通常會在所宣告的結構裡宣告兩個結構指標,如下所示:
struct student {
char name[16];
int id;
struct student *next, *prev;
};

只要經由prev與next兩個結構指標,便能取得該doubly linked list所有資訊。

然而,Linux kernel並非引用此種作法。因此,Linux kernel定義一通用結構 (struct list_head, include/linux/list.h),用以實作doubly linked list,此結構相當簡單,如下所示:
struct list_head {
struct list_head *next, *prev;
};


所以物件student宣告為如下:
struct student
{
char name[16];
int id;
struct list_head list;
};

藉由list變數便能取得doubly linked list所有資訊。

list_head相關Marco與Function

這裡僅介紹較常用的macro與function,如欲進一步得知其它marco請參考include/linux/list.h


LIST_HEAD(name)
struct list_head name = { &(name), &(name) };
將next與prev指到自己,意味著此list為空的。

list_empty(const struct list_head *head)
retrun head->next == head;
檢查此list是否為空的。

list_add(struct list_head *new, struct list_head *head)
head->next->prev = new;
new->next = head->next;
new->prev = head;
head->next = new;
將資料加入至doubly linked list最前端。建議自己動手畫個圖,便可了解這幾個指標指到何處。

list_del(struct list_head *entry)
entry->next->prev = entry->prev;
entry->prev->next = entry->next;
將某一資料從中刪除。

list_entry(ptr,type,member)
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
透過此函式便能算出結構的起始位址,並做結構轉型便能取得結構的資料,此計算方式相當好用啊!!!
以struct student為例,如下所示:
  1. (unsigned long)(&((struct student *)0)->member))) ==> 計算出list成員相對位址。通常看到這一個敘述,直覺地覺得應該會記憶體區段錯誤吧 (Segmentation Fault)!? 因為該敘述用NULL的pointer存取list成員,但在(struct student *)0)->member))前面加了&符號,就不會發生記憶體區段錯誤。因為&符號,只意味著存取list的位址,而不是資料,經由此敘述便能取得list的位移植。如下圖所示,該敘述所得之位移植值為20。
    list_head
  2. ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) ==> 取得位移植之後,再將list的位址減去位移植,便能取得該結構的起始位址,如下圖所示 (假設結構起始位址為x),最後再做結構轉型變大功告成。
    list_entry
list_for_each(pos, head)
for (pos = (head)->next; pos != (head); pos = pos->next)
取得該doubly linked list所有資料。

範例程式
光看這些Macro跟函式可能比較無法有sense,因此小弟寫了一簡單的程式,有興趣的可以下載此範例程式玩玩看。XDD

[Reference]
Understanding the Linux Kernel, Third Edition
Linux Kernel Source Code Version 2.6.20-15

2007年10月12日 星期五

Vim Plugin: 好用的C函式庫參考手冊 (CRefVim)

是否曾在coding的時候,知道函式名稱卻忘了如何傳遞參數? CRefVim Plugin會是您的好幫手, 至Vim官網下載並按照齊步驟安裝,便能有此功能。

功能說明
  1. 在Vim常態模式 (Normal Mode)按"\cw",便會出現"What to lookup:",輸入欲查詢的函式名稱。
  2. 編輯一個C語言原始檔,此原始檔有memset函式,假設欲查詢memset函數說明,將游標移至memset再按\cr,就可以嚕!!

2007年10月5日 星期五

Linux Kernel: 簡介HZ, tick and jiffies

Linux核心幾個重要跟時間有關的名詞或變數,底下將介紹HZ、tick與jiffies。

HZ
Linux核心每隔固定週期會發出timer interrupt (IRQ 0),HZ是用來定義每一秒有幾次timer interrupts。舉例來說,HZ為1000,代表每秒有1000次timer interrupts。HZ可在編譯核心時設定,如下所示 (以核心版本2.6.20-15為例):
adrian@adrian-desktop:~$ cd /usr/src/linux
adrian@adrian-desktop:/usr/src/linux$ make menuconfig
Processor type and features ---> Timer frequency (250 HZ) --->

其中HZ可設定100、250、300或1000。以小弟的核心版本預設值為250。

小實驗
觀察/proc/interrupt的timer中斷次數,並於一秒後再次觀察其值。理論上,兩者應該相差250左右。
adrian@adrian-desktop:~$ cat /proc/interrupts | grep timer && sleep 1 && cat /proc/interrupts | grep timer
0: 9309306 IO-APIC-edge timer
0: 9309562 IO-APIC-edge timer

上面四個欄位分別為中斷號碼、CPU中斷次數、PIC與裝置名稱。



問題來了,timer interrupt會做哪些事情? 答案如下所列:
  • 更新時間、日期與系統從開機至目前經過多少時間 。
  • 更新系統資源使用率統計
  • 檢查正在執行的程序是否已經超過其所分配的執行時間額度。如果是的話,則侵佔(preempt)該程序以利執行其它等待執行的程序。
  • 檢查軟體時間器(Software timer,如alarm系統呼叫)跟時間延遲函式(Delay function)的延遲時間是否已經超過。
Tick
Tick是HZ的倒數,意即timer interrupt每發生一次中斷的時間。如HZ為250時,tick為4毫秒 (millisecond)。

Jiffies
Jiffies為Linux核心變數(32位元變數,unsigned long),它被用來紀錄系統自開幾以來,已經過多少的tick。每發生一次timer interrupt,Jiffies變數會被加一。值得注意的是,Jiffies於系統開機時,並非初始化成零,而是被設為-300*HZ (arch/i386/kernel/time.c),即代表系統於開機五分鐘後,jiffies便會溢位。那溢位怎麼辦? 事實上,Linux核心定義幾個macro(timer_after、time_after_eq、time_before與time_before_eq),即便是溢位,也能藉由這幾個macro正確地取得jiffies的內容。

另外,80x86架構定義一個與jiffies相關的變數jiffies_64 ,此變數64位元,要等到此變數溢位可能要好幾百萬年。因此要等到溢位這刻發生應該很難吧。那如何經由jiffies_64取得jiffies資訊呢? 事實上,jiffies被對應至jiffies_64最低的32位元。因此,經由jiffies_64可以完全不理會溢位的問題便能取得jiffies。

2007年10月2日 星期二

StarDict也可發音

如同Dr.eye一樣,StarDict也可單字發音,其設定如下:

  • 至Sourceforge下載WyabdcRealPeopleTTS檔案
  • 將WyabdcRealPeopleTTS.tar.bz2解壓縮,解壓縮會產生WyabdcRealPeopleTTS資料夾,將其資料夾移至/usr/share/即可。
  • 重新啟動stardict,查詢單字看看吧!!

[Reference]
海芋小站 - 介紹一系列StarDict設定

2007年10月1日 星期一

Vim Tip:在原始檔與標頭檔之間切換 (Switch between source file and header file)

之前使用Anjuta有一個很方便快速鍵可以切換原始檔與標頭檔,但最近一直搜尋Vim是否也有此功能? 答案是有的,廢話不多說,設定如下:
  • 編輯~/.vim/ftplugin/c_extra.vim,加入底下兩行
  • nmap ,c :find %:t:r.c ---> 將,c對應至搜尋原始檔(也就是.c檔)
  • nmap ,h :find %:t:r.h ---> 將,h對應至搜尋標頭檔(也就是.h檔)

如此便大功告成


[Reference]
Vim tip website