2007年12月29日 星期六

Linux Kernel Patch: 使用 sysctl 控制 idle method

Standard
到了今天,SMP系統已經很常見,街上隨便抓一台 NB 都是雙核心的架構。但也因為是 NB,又常搭配 NVIDIA 的顯示晶片,我們必須對 idle method 做適當的調度,以保持其穩定性和續航力。在過去,我們在開機就必須指定 BootPrompt 以決定 idle method,這對 LiveCD 和各 Linux 套件實在不是很好,因為在 Boot Loader 時,我們並不曉得該台電腦的狀況,無法判斷是否該用 poll idle 的方式啟動 Kernel。

因此,我針對這問題對 Linux Kernel 做了一個 patch ,讓用戶可以在進入作業環境後,從 /proc/sys/kernel/ 中即時開關 poll_idle(),以便硬體偵測程式可以依系統需求,動態去啟動 poll_idle()。

這次的 patch 可由此下載:linux-kernel-2.6.23.9-idle_poll_sysctl.patch

2007年12月28日 星期五

老莊有理,惡搞無罪

Standard
哲學是非常奧妙的一門學問,它探討了這宇宙的構成與真理,卻又不涉及尖端科技的理論,完全以邏輯的方式證明這個世界。如果說現在最先進的科技,是尋找無限放大的世界,那麼,最高等的哲學就是尋找無限縮小的世界。這兩種世界從字面上分析是相反的,但我們卻不難體會出其中兩者一體的絕妙之處。中國道家學說就是建立在這巨觀的基點上,常聽到的莊周夢蝶,就是這麼一回事。

雖然在今日,眾多西洋哲學林立,其中也不泛有好的理論,但我個人總是偏好道家莊子一派。大家都曉得道家是以老、莊為代表人物,歷史上總是以『清淨無為』為定位,所衍生出來的『無為而治』解釋更鬧出不少笑話。我無法對後人的譯文做評論,但我相信如果老子對自己所創造的學說了然於胸,他口中的『無為而治』就並非後人所解釋的『無為而治』﹝因為後人對這句話的認知和道家學說本身矛盾﹞。先不論老子是否有自相矛盾之舉,莊子在這方面表現的較無爭議,因此個人較偏好莊子一派。

道家認為世界萬物,都是處於道德之中﹝並非仁義道德的道德,簡單來說道德就是包括時間、空間和所有東西的大宇宙﹞,我們活在這大宇宙的洪流之中,隨著時間、萬物一同漂蕩。也就是說我們是被這大宇宙所掌握,如同我們掌控手中的一杯拿鐵一般。別以為你擁有不被掌控的選擇,因為你的身體、心靈、智慧、想法都是在這宇宙的洪流之中產生,冥冥之中,你所有的一切都不是你的,我們的想法其實是道德要我們產生的想法,我們的所作所為也是道德要我們去做的,換言之,我們的一切,就是道德的一切,也是道德透過我們在做的一切。

曾經就有人斷章取義,以『既然我無法決定我自己,那大家都擺爛,看這世界會如何。』試圖證明道家學說的荒謬。看起來這個人說的話好像是正確的,但其實他弄錯一點,大家擺不擺爛,也是由道德所決定,因為除少數人外,你我都不會有意願擺爛,他的假設也就不會成立。

其實,用個簡單的邏輯就可以很容易明白這道理。

道德掌控人 → 人掌控想法 → 人想改變道德


結論是,除非道德本身要改變,否則人是無法躍過層級去改變道德的。

如果我們將道德用『神』一詞取代,道家的觀點有點神論的味道,但更激烈的是道家認為這世上只有神的存在,人根本不算個東西。其實,將道德換成『基因』就更明瞭了,但多數人只可以接受有東西在控制他的身體,卻不接受有東西在控制他的想法﹝因為人都覺得自己可以改變一切呀!﹞。

講了這麼多,道家學說到底要告訴我們什麼呢?其實就是純開槓、打屁。只有你去忘記道德的存在,才是真正的自然的活在這宇宙之中。還有,道家學說告訴我們,我們和地上的一坨屎是沒兩樣的。

最近有哲學系的朋友要交中哲方面的報告,跑來問我一些老莊問題,引起我多年沒有回味的一些想法,雖然莊周的思想有相當的正確性,但多半都是純打屁的東西,沒多大實用價值,除非是研究理論,不然還是不碰為妙。像『無為之治』這種走火入魔之道,實在不是什麼光彩的事。

但原本惡搞的人還是惡搞吧!老莊支持你!

2007年12月27日 星期四

關於 Linux BootPrompt "idle=" Argument

Standard
關於 Linux 的核心開機參數 idle,在之前的文章『不必灰心!NVIDIA GeForce Go 7300 的擁有者!』已經使用過,不過當時只知道可以用來解決某些 NVIDIA 顯示晶片的問題,並不曉得其真正用途與目的。

經過查詢後,在 TLDP 找到了 BootPrompt HowTo,並在『 General Non-Device Specific Boot Args 』章節找到了一段 idle 參數的說明。

Setting this to 'poll' causes the idle loop in the kernel to poll on the need reschedule flag instead of waiting for an interrupt to happen. This can result in an improvement in performance on SMP systems (albeit at the cost of an increase in power consumption).


設 idle=poll 會使 kernel 使用 idle_poll() 取代原有 idle() 的 HLT instruction,提高 SMP 系統的運算效能。另外,因為 idle_poll() 的機制會使 CPU 使用率變高,所以相對的也會耗費更多的電力。如果是單核心 CPU 的環境,就不用考慮了這個機制了,基本上在單核心的環境之下使用 idle_poll() ,只會造 CPU 更大的負擔,效能可能會更差。

現在想想,之前 NVIDIA GeForce Go 7300 也是在雙核心的 CPU 上跑,或許是因為官方的 Driver 對 SMP 的支援還有問題。

2007年12月26日 星期三

不必灰心!NVIDIA GeForce Go 7300 的擁有者!

Standard
這兩天使用 ASUS A8T NB 做系統的支援度測試,如預期的一切都很正常,唯一有問題的是,系統死當!這死當不只是 Xorg 當掉,也不只是 OS Kernel Crash,是整個電腦忽然間 Freeze!﹝自從 Win95/98 後已經幾乎沒碰過這樣的狀況了﹞

經過 Debug 後,發現是 NVIDIA 官方驅動和 Compiz 所造成的。但無論我升級成什麼版本的 Driver﹝我已經衝到12/20才剛出來的 169.07 版﹞,一樣是死掉。上網尋找是否有人碰到跟我相同的狀況,結果只找到各式各樣使用 NV 6200/7200/7300 所碰到的問題,當然和碰到跟我一樣狀況的人也是有,但都是無解。

好吧,我該放棄了。正準備將 ASUS A8T NB 加入到不支援名單時,看到一篇 ASUS A6T 的 Linux 使用報告﹝http://gentoo-wiki.com/HARDWARE_Asus_A6T﹞,由於 A6T 所使用的顯示晶片和 A8T 是一樣的,所以我很認真的讀完了它。文件中所說的重點,我大致上都了解,但有一點比較特殊,是在 Boot Prompt Command 加上『idle=poll』,文件中說這可以增進使用 GPU 的系統穩定度。於是活馬當死馬醫的我就照做了,哈哈!Bingo!問題終於解決!

碰到跟我一樣問題的人可以試試這方法!NVIDIA GeForce Go 7300 的擁有者們!

後記

提醒我,該去查查 idle=poll 到底是做什麼用的。

2007年12月25日 星期二

lxpanel Patch: 修正與 compiz cube 的相容性問題

Standard
電腦的演進神速,轉眼就到了 3D Desktop 的時代。雖然許多人追求輕便型的桌面環境,但如果不嘗嘗 CompizFusion 所帶來的超酷視覺享受,似乎對不太起今日的電腦硬體 :P

這幾天發現 lxpanel 和 compiz cube 有相容性的問題,也就是 viewport 不會跟著 active 的視窗轉動。這問題牽涉到 EWMH 規範的操作,簡單修正後 lxpanel 的 taskbar 已經能正常切換工作並更改 viewport 狀態。

想修正的人可以使用這 patch:lxpanel-0.2.4-viewport.patch

2007年12月23日 星期日

oxim Patch: 更進一步改善 X event 處理機制

Standard
關於 oxim 的 xevent 處理機制所造成的 bug 在前一次 patch 時已經提過﹝請參閱『oxim Patch: Event BUG』﹞,由於網友 swyear 的告知,也意外的發現在 openSUSE 10.3 上有相同原因所造成的困擾。

經過這兩天測試後,發現前一次的 patch 雖然解決了無法正常啟動 oxim 的問題,但是其運作的並不穩定,有死掉、呆掉的情況發生,而且造成的 CPU 負擔甚大。所以,這次用 select 更進一步改善了 oxim 對 X event 的處理機制。

關於這次的 patch:oxim-1.1.3-xevent-20071223.patch

2007年12月20日 星期四

oxim Patch: Event BUG

Standard
最近移植 oxim 時碰到一個問題,就是當我使用 xinit 啟動 X Server 和 oxim 時,oxim 會 wait 在那動都不動,使用 strace 也無法 debug,因為一旦以 strace oxim 這樣的方式啟動 oxim,它就沒這個問題。﹝什麼!?這 Bug 還會自動躲 debug 程式!﹞

一邊努力 debug 一邊在 IRC 上抱怨,最後終於靠 jserv 的建議與指導之下,用了 gdb + XSynchronize() 找出了出問題的地方,果然皇天不負苦心人啊!

問題出在 oxim 對 gui event 的處理,大概是使用 xinit 直接啟動的環境太簡單乾淨,oxim 的 Trayicon 等需要 GUI 的部份完全收不到 X 的 event,所以就停在 XNextEvent 苦命等待。

不過就在解決掉 event 等待的問題後,我將 debug 時用的 XSynchronize() 移除,隨即碰到的就是 GUI 重繪問題。雖然 oxim 順利的啟動了,但選字區、選單都一片空白,將 XSynchronize 開啟就正常,這點非常怪異令我不得其解,不過想到 oxim 只是處理使用者輸入中文,對 graphic 的處理速度並不非常要求,所以我將 XSynchronize 保留。

關於這次的小修正,我已經做成 patch:oxim-1.1.3-xevent.patch

2007年12月14日 星期五

OrzMicrokernel main.asm 核心啟動主結構

Standard
作業系統核心的運作分兩個階段,第一個階段是初始化,第二個階段是規律的活下去。從第一階段到第二階段的流程和主結構都清楚地寫在 main.asm,而工作排程、記憶體規劃等設計都是由此再延伸出去。

main.asm 原始碼:
%include "defines.asm"
%include "orzmicro.inc"
%include "16bit.asm"
%include "32bit.asm"

;-----------------------------------------------------------------------------------
; Now, we are under 32 bit protected mode. Starting...

mov al,1 ; 設定為 320x200 的圖形模式
call SetVideoMode ; 呼叫 video.asm 的子程式設定顯示模式

call InitTasks ; 呼叫 tasks.asm 的子程式初始化工作狀態記錄表

mov eax, Ts1 + 0x10 ; 設 EAX 為工作記憶體開始位址
mov ebx, Ts2 - Ts1 - 0x10 ; 設 EBX 為工作所佔記憶大小
mov ecx, [Ts1 + 8] ; 設 ECX 為工作二進位檔的第 8 個 bytes 所設定的堆疊大小
mov edx, [Ts1 + 12] ; 設 ECX 為工作二進位檔的第 12 個 bytes 所設定的資料大小
mov esi, ts1Name ; 設 ESI 為工作名稱
call CreateTask ; 呼叫 tasks.asm 的 CreateTask 子程式建立工作

mov eax, Ts2 + 0x10 ; 設 EAX 為工作記憶體開始位址
mov ebx, Ts3 - Ts2 - 0x10 ; 設 EBX 為工作所佔記憶大小
mov ecx, [Ts2 + 8] ; 設 ECX 為工作二進位檔的第 8 個 bytes 所設定的堆疊大小
mov edx, [Ts2 + 12] ; 設 ECX 為工作二進位檔的第 12 個 bytes 所設定的資料大小
mov esi, ts2Name ; 設 ESI 為工作名稱
call CreateTask ; 呼叫 tasks.asm 的 CreateTask 子程式建立工作

mov eax, Ts3 + 0x10 ; 設 EAX 為工作記憶體開始位址
mov ebx, Ts4 - Ts3 - 0x10 ; 設 EBX 為工作所佔記憶大小
mov ecx, [Ts3 + 8] ; 設 ECX 為工作二進位檔的第 8 個 bytes 所設定的堆疊大小
mov edx, [Ts3 + 12] ; 設 ECX 為工作二進位檔的第 12 個 bytes 所設定的資料大小
mov esi, ts3Name ; 設 ESI 為工作名稱
call CreateTask ; 呼叫 tasks.asm 的 CreateTask 子程式建立工作

mov eax, Ts4 + 0x10 ; 設 EAX 為工作記憶體開始位址
mov ebx, Ts5 - Ts4 - 0x10 ; 設 EBX 為工作所佔記憶大小
mov ecx, [Ts4 + 8] ; 設 ECX 為工作二進位檔的第 8 個 bytes 所設定的堆疊大小
mov edx, [Ts4 + 12] ; 設 ECX 為工作二進位檔的第 12 個 bytes 所設定的資料大小
mov esi, ts4Name ; 設 ESI 為工作名稱
call CreateTask ; 呼叫 tasks.asm 的 CreateTask 子程式建立工作

mov eax, Ts5 + 0x10 ; 設 EAX 為工作記憶體開始位址
mov ebx, Ts6 - Ts5 - 0x10 ; 設 EBX 為工作所佔記憶大小
mov ecx, [Ts5 + 8] ; 設 ECX 為工作二進位檔的第 8 個 bytes 所設定的堆疊大小
mov edx, [Ts5 + 12] ; 設 ECX 為工作二進位檔的第 12 個 bytes 所設定的資料大小
mov esi, ts5Name ; 設 ESI 為工作名稱
call CreateTask ; 呼叫 tasks.asm 的 CreateTask 子程式建立工作

mov eax, Ts6 + 0x10 ; 設 EAX 為工作記憶體開始位址
mov ebx, Ts7 - Ts6 - 0x10 ; 設 EBX 為工作所佔記憶大小
mov ecx, [Ts6 + 8] ; 設 ECX 為工作二進位檔的第 8 個 bytes 所設定的堆疊大小
mov edx, [Ts6 + 12] ; 設 ECX 為工作二進位檔的第 12 個 bytes 所設定的資料大小
mov esi, ts6Name ; 設 ESI 為工作名稱
call CreateTask ; 呼叫 tasks.asm 的 CreateTask 子程式建立工作

jmp Schedule ; 啟動工作排程器,核心初始化到此為止

; Default tasks (entries)
; 將磁碟機、FAT12、Console、鍵盤等操作處理服務併入
; Orz MicroKernel 的設計,讓所有的硬體驅動等服務和核心分開。
; 雖然這些服務會被併入核心的程式檔內,但其實它們是個別的程式且獨立於核心架構之外。
; 被核心載入記憶體時,會被當成一般 User Mode 的工作執行。
; 所以,要是這些所謂的『驅動程式』出問題,不會導致核心崩潰當機。
Ts1: incbin "tasks/bin/exec_library.bin"
Ts2: incbin "tasks/bin/floppy_device.bin"
Ts3: incbin "tasks/bin/fat12_handler.bin"
Ts4: incbin "tasks/bin/init.bin"
Ts5: incbin "tasks/bin/console_library.bin"
Ts6: incbin "tasks/bin/keyboard_handler.bin"
Ts7:

; Default task names
ts1Name db "exec.library",0
ts2Name db "floppy.device",0
ts3Name db "fat12.handler",0
ts4Name db "init",0
ts5Name db "console.library",0
ts6Name db "keyboard.handler",0

;-------------------------------------------------------------------------------

%include "helper.inc"
%include "globals.asm"
%include "video.asm"
%include "mm.asm"
%include "tasks.asm"

%include "realmode.asm"
%include "irqs.asm"
%include "kprint.asm"
%include "gpfault.asm"
%include "except_fault.asm"
%include "irq_handlers.asm"
%include "messages.asm"

%include "tables.asm"



後記

其實我應該先寫 main.asm 的註解才對,畢竟這才是 Orz MicroKernel 的根。而其他枝芽,都是這之後的事了。

遺忘 Orz MicroKernel 有一陣子了,因為碰到期中考,又碰到很多事要忙,所以就只好擱著了。

2007年12月12日 星期三

Aufs Overlap Check Bug

Standard
Aufs 是一個能結合各種 FileSystem 到同一個分區的聯合檔案系統機制,它在這兩年內快速竄起,取代了其 Unionfs 的地位。而關於其歷史背景和較詳細的介紹,有興趣的人可以參考我過去的文章『取代Unionfs的好東西 - Aufs』。

還記得我最後一次 Compile Aufs 是在去年底今年初的時候﹝抱歉。詳細日期記不太清楚﹞,使用 CVS 直接從 SourceForge 取得的最後版本﹝Aufs 專案本身沒有提供打包好的 Source Package 只能用 CVS 取得﹞。Aufs 被我使用在當時正在研發的一些 Embedded 系統內,將原本的 rootfs 放在 Aufs 之上以得到更多的擴充性。我將所有的 FS-Modules 藉由 loopback 而 mount 到 /dev/unionfs/[0-X] 之中,最後再用 Aufs 將這些目錄與 rootfs(/) 做結合。那時候一切都很正常,我也很滿意。

這幾天,因為舊 Linux Kernel 許多的 Bug 和缺少某些 Device Drivers 的情況下,我只好將 Kernel 更新並重新 Compile 來一勞永逸,順帶了也更新了一些 patch 和功能的版本,而 Aufs 就是在這幾天被我更新的。可是當一切準備就續後,卻發現 Aufs 在我的系統上總是出現 Overlapped 的訊息,它不讓我將 /dev/unionfs/[0-X] 加入到根目錄的 Aufs 上。之後搞了半天,才發現 Aufs 這幾個月的更新,使檢查 Overlap 的部份有錯誤。

於是,我直接將檢查 Overlap 的 function 的 return,改成 Always 回傳沒問題,這問題就解決了。當然,這是『不正確』的方法,我只是讓 Aufs 跳過不檢查是否有 Overlap 的情形發生。要是碰到出狀況,無限循環會讓系統整個大亂,到時候就欲哭無淚。

2007年12月11日 星期二

我有羽毛‧我會展翅

Standard
剛跟父親吵過一架,我們吵架不外乎就是對某些事的見解不同。近年來除非是突如其來的大吵,多半時候只是耳聞不回應,就這樣避開了取多爭執的機會。

老實說,我老是被父親抓得緊緊的,保護的異常的好,各方面的起步與發展,也都是因為他而啟蒙。從他身上,我的確學會了很多平常人沒機會接觸的東西與經驗,也看到了許多未來的目標和前景。就因為這些不同的經驗和想法,無形之中自我限制了不少事情,因此有很多時候不像同年紀的人一般自在,但也讓我感受到這世界的多采多姿。

我慢慢長大,雖然就全方位來說,我仍是生澀的小毛頭,但就部份成果來說,我卻也有一定的功力和能力,尤其某些特定領域,我更是投注完全精力去一窺天地。不知不覺,在這些部份,已經漸漸超出父親所能掌控了解的範疇。一切來的這麼不著痕跡,當然在這兩方面見解所產生的爭議,也越來越頻繁。

就某些領域,父親雖然已經不能再提供我更多知識,但是他嘗試告訴我更多的心,我很感激。可是父親的不放手,卻也讓我步步艱辛,彷彿我了解更多,我就有更大的問題一樣。如此而爭吵,一點都不必要。羽毛長出來了,卻要我一根根拔掉,更是不必要。怕我著涼,又為我植下更多的羽毛,這又是何苦?

我曾經嚮往奔放體育,嚮往揮灑藝術,嚮往打滾人際,但是,如今卻一一捨去。因為你讓我瞭解,如此盲目嚮往是沒有未來的。今天,我只是個在大型溫室中的花朵,巢中的殘雉,已經沒有了過去的一切。如此的我,能不堅持僅存的一些理想和想法嗎?

2007年12月1日 星期六

實作 Linux 下的硬體自動偵測:X.Org 驅動程式

Standard
關於自動偵測 PCI 裝置實作的部份,在『實作 Linux 下的硬體自動偵測:PCI 裝置』已經提過,應該有九成以上的硬體,都可以如預期的被辨識且載入適當的驅動模組。但是,那只限於 Linux Kernel 的驅動模組被正確配置而已,對於常用到的顯示卡而言,能正確設定 X.Org 的設定檔 xorg.conf 才算真正達成自動偵測的目的。﹝傳言新版的 xorg.conf 已不需要再特別設定,但我沒試過,還請用過的人能告知小弟。﹞

相對 Linux Kernel 有 modules.pcimap , X.Org 有 *.xinf 可以讓我們比對顯示卡 Vendor:Device 和 xorg driver 的關係,可以在 /usr/share/hwdata/videoaliases/*.xinf 找到一系列 xorg 顯示卡驅動程式的對應資料檔。

舉例來說 opensource nvidia driver 對應到的 nv.xinf,檔案資料的格式大致如下:

alias pcivideo:v000010DEd00000427sv*sd*bc*sc*i* nv # g80

其中 v000010DE 和 d00000427,就是硬體的 Vendor:Device。由此,我們就可以仿照之前偵測 PCI 裝置的方法,找到顯示卡對應的 xorg driver。

可以參考這段簡單的 Script Function:
# findxorgmodule [vendor] [device]
findxorgmodule() {
# Transforms lowercase characters into uppercase
VENDOR=`echo -n ${1} | tr [a-z] [A-Z]`
DEVICE=`echo -n ${1} | tr [a-z] [A-Z]`
for VIDEOINF in /usr/share/hwdata/videoaliases/*.xinf; do
while read HEADER DEVICEID MODULE COMMENT; do
if [ x"$HEADER" = x"alias" ]; then
echo $MODULE
return
fi
done >>-EOF
$(grep "pcivideo:v0000${VENDOR}d0000${DEVICE}" $VIDEOINF)
EOF
done
}


如果要偵測 nvidia 的官方驅動程式,目前沒有現成的 .xinf 可以使用,要自己去官方網站的硬體支援列表抓下來轉成 .xinf 才行。另外,nvidia 的官方驅動有分新舊版,分別是支援較新和最老舊的晶片,關於這部份的自動偵測與配置,還要搭配一些額外的處理才行。

後記

大概不會有人和我一樣這麼低能,沒事自己手工打造一個 Linux distribution,從 Kernel, Init RCs, Hardware Detection, networking setting, Harddisk/LVM/RAID...全動自己重新調配或重頭寫。其中過程的很多經驗都屬沒實質用途居多,像是『實作 Linux 下的硬體自動偵測』就是對一般人沒什麼用的東西,純粹是惡搞、浪費時間、虐待自己的小經驗。:P

只要有樂趣,虐待自己也沒什麼不好!﹝笑﹞