C 編譯器跟你想的不一樣
2008 年筆者在 COSCUP 發表了題目為「
我是軟體 -- 那些處理器教我的事」的演講,探討因為處理器架構與系統軟體組態或假設不同,導致一連串令人意外的結果,著眼於涉及跨平台開發所潛藏有如未爆彈的種種議題。日前嘗試修改某個客戶的專案,沒想到又踩到另一個地雷,自詡是「
慣 C」迷的筆者,萬萬沒想到還得交叉對照組合語言輸出,才克服問題,撰文分享如下。
考慮以下程式碼:(test.c)
#include <stdio.h>
#define DEBUG 1
#define DBG( ... ) \
if (DEBUG) { __VA_ARGS__; }
int main(int argc, char *argv[]) {
char *num;
switch (argc - 1) {
case 0: num = "zero";
DBG( case 1: num = "one"; )
DBG( case 2: num = "two"; )
DBG( case 3: num = "three"; )
DBG( default: num = "many"; )
while (--argc)
printf("%s ", argv[argc]);
printf("\nArgument count: %s\n", num);
break;
}
return 0;
}
先不看 DBG() macro 的使用,似乎沒什麼特別之處,編譯並執行看看:
$ gcc -Wall -o test test.c
$ ./test 1 && ./test 1 2 && ./test 1 2 3 && ./test 1 2 3 4
1
Argument count: many
2 1
Argument count: many
3 2 1
Argument count: many
4 3 2 1
Argument count: many
完全符合預期,就是把 switch-case 走訪一遍,因為沒有 break 敘述,就到了最終的 "default" 條件,所以 char *nnum 指向字串 "many" 的記憶體位址。但倘若我們將第二行的 DEBUG 定義修改為以下:
#define DEBUG 0
再來重新編譯與執行看看:
$ gcc -Wall -o test test.c
$ ./test 1 && ./test 1 2 && ./test 1 2 3 && ./test 1 2 3 4
1
Argument count: one
2 1
Argument count: two
3 2 1
Argument count: three
4 3 2 1
Argument count: many
這是什麼狀況呢?被一串 if (0) { ... } 包圍的 switch-case 竟然會被處理,而且 break 巧妙地伴隨每個敘述出現。也就是說,原本的 "DBG( case 1: num = "one"; )" 相當於 break; case 1: num = "one; break; 的效力。像這樣的 C 語法結構,可歸納為 [
Clifford's Device],簡單來說,就是符合以下的結構:
if (0) { label: ... }
引述網頁描述:
"it is skipped in the normal flow of execution and is only reached via the goto label, reintegrating with the normal flow of execution and the end of the if (0) statement. It solves a situation where one would usually need to duplicate code or create a state variable holding the information if the additional code block should be called."
在普通的執行流程中,if (0) { ... } 包圍的陳述指令會被忽略,但倘若配合 goto 時 (本例是 switch-case,一個 C 語法的變形),就不是這麼一回事,翻譯成組合語言或機械碼時,其實是很清楚且常見的結構。這樣的結構對於縮減煩冗的程式碼有些特別用途。上述程式碼有趣之處,就在於像 DBG() 這類的 macro 在前期開發階段通常被設定為 "1",在後期則會逐步取消偵錯 / 驗證的程式碼時,將 macro 改為 if (0) { ... } 型態,而使開發者誤踩到「未爆彈」。
由 jserv 發表於
1:21 PM
|
迴響 (0)
演講:L4 microkernel 的背景知識與最新的研究發展
今年二月 7 日,小弟將分享關於 L4 microkernel 的背景知識與最新的研究發展,詳情請參考 [
星系統社群:第5次星系主題-L4 microkernel 的背景知識與最新的研究發展]。
第一次見到 [
L4 microkernel],是在 William Stallings 的 [
作業系統叢書] 讀到,那時是 1997 年,僅提供七個系統呼叫但可搭建完整作業系統基礎的 microkernel,對當時還在唸高中的我,實在是不小的衝擊。高中住校沒有辦法使用電器設備,遑論使用網際網路,唯一獲取知識的方法,就是利用每天宿舍晚自習結束到關大門前的短暫一個半小時,去附近的書店啃書,William Stallings 的大作闡述作業系統非常透徹,而關於 L4 的部份,更激起我的興趣,但這類的書籍往往售出後,就很少進貨,而我身上根本沒什麼零錢,結果一時鋌而走險,竟然沒購買而擅自攜帶出去。這本書伴隨著我在高中的課餘生涯,也讓「系統程式」與我結下不解之緣。
像這樣去附近的店家「借取」(一開始真的有歸還,但後來就無疾而終) 了好幾本關於作業系統、編譯器設計、Linux / BSD 系統書籍的行徑,是高中生涯很特別的插曲,但「偷書」是事實,估計總價約台幣五千多元。後來接了案子,逐漸有能力償還時,這些店家要不倒閉,不然就是不接受我的賠償,於是愧疚了十多年。這幾年購書,往往會要求不打折,不然就是同一本書一次多買幾份,送給需要的朋友,此外,我持續地作免費的資訊技術分享,就是希望能多作點補償。因為談及 L4 microkernel,也抖出「偷書」的陳年往事,如今探討這個議題,自然是五味雜陳,本議程最早規劃在去年,追憶 L4 發明人 Jochen
Liedtke 教授過世十週年,不過當時有事耽擱,只好在今年擇期探討。
L4 在上個世紀末證明,microkernel 的效能落差並非本質的限制,而是設計與實做的議題,也因此,L4 這個高效能的 microkernel 被稱為「第二代 microkernel」, 有鑑於 CMU Mach microkernel 的若干低效能表現 (如 IPC),L4 進一步做出精簡的設計,只 7 個系統呼叫,而且核心本身只有 12 Kbytes,只實現以下三個抽象概念的基礎建設:
藉由充分使用硬體機制來實現,大幅縮減 TLB 與 cache miss 的開銷。這十年來,無論是原本從事 microkernel 抑或 RTOS 開發的廠商與研究單位,則逐漸往虛擬化技術 (virtualization) 靠攏,愈來越多技術發生「大融通」的效應,而本議程則著眼於 L4 microkernel 與日益多元的應用方式,介紹其背景知識與發展,預定提綱如下:
- Myths of Microkernel
- Characteristics of second generation microkernel
- Key services: memory, thread, IPC management
- L4 in real world: distributed, virtualization, and reliability
如同之前的演講 [
Embedded Hypervisor for ARM],小弟也會發表一項新專案,這是個極小的 L4 microkernel 與作業系統環境的實做,在某個程度上,可說是回應了 2007 年發表的 [
Orz Microkernel]。期待您的指教與交流,謝謝!
由 jserv 發表於
11:36 AM
|
迴響 (0)
"Develop Community-based Android Distribution and Upstreaming Experience" 簡報上線
去年十一月有幸受 [
droidcon] 的邀請,到荷蘭阿姆斯特丹分享關於 [
0xlab] 兩年來的開發經驗,探討我們如何累積基於 Android 的技術,並且透過 open source 的力量,回饋到社群並為我們創造更多正向的開發機會。簡報已上線,請見: [
dev-android-distribution.pdf]
提綱如下:
- Reasons to build Android distribution
- Lesson learned from AOSP
- The methods to enhace Android software stack
- Go upstream
包含之前去 [
Embedded Linux Conference Europe ] 演講的經驗在內,這兩次都讓相當感動,雖然極少有亞洲面孔的與會者,但只要展示出 [
0xlab] 與介紹 open source,有不少人就認得我們,還談了頗多關於台灣品牌的議題,非常激勵人心。
由 jserv 發表於
2:49 PM
|
迴響 (0)
「用 Android 學習系統程式」簡報上線
上個月筆者在台南崑山科技大學演講「
用 Android 學習系統程式」,簡報已上線,請參考 [
discover-android-system.pdf]
自 2006 年起,筆者分享了名為「深入淺出 Hello World」的系列演講後,獲得一些迴響與啟發,而隨著 Android 裝置的普及與整體硬體的提昇後,實際在大量使用的裝置如智慧型手機上,做觀察、分析,進而研究系統程式的原理,已是相當便利。本議程可視為「
深入淺出 Hello World」的實務篇,企圖從觀察 ARM/Linux 的運作開始,延伸去年的演講主題 [
自己動手,豐衣足食 -- 淺談探索 Linux 系統設計之道],透過現有 Linux 核心與 Android 系統的若干機制,逐步揭開系統程式的面紗。
議題大綱:
- 握在手心的 Linux 核心: 工具與環境準備
- 從 Hello World 等級的程式分析起
- 探索記憶體模型
- 核心與使用者層級程式的互動
除了原本「
深入淺出 Hello World」探討的項目外,這次追加了 ARM 與 Binder IPC 的子項目,由於是第一部份,並未深入細節,不過仍是如過往一般,強調尋幽訪勝的方法,而稍候預計會有銜接的系列演講,還請多多指教,謝謝!
PS: 本系列議程也規劃有台北、新竹的場次,但目前需要熱心朋友協助安排場地,基於知識分享交流的動機,全系列的演講都是公開免費的形式,歡迎與本人聯繫。
由 jserv 發表於
12:00 AM
|
迴響 (0)