發表文章

目前顯示的是 十一月, 2007的文章

實作 Linux 下的硬體自動偵測:PCI 裝置

x86 的硬體分為很多種類別,從早期的 ISA 一直到後來的 PCI、PCMCIA、USB,都有各自的硬體接角定義,要辨識這些裝置,得靠這些硬體通電與主機板連接後,所提供的自身資訊。

就最常用到的 PCI 裝置來說,目前有 99.999% 的硬體都是歸屬於 PCI 裝置﹝包括AGP、主機板上的各種控制晶片﹞。所以,只要能夠正確辨識 PCI 裝置並載入相對應的 Modules,就能夠對大部份硬體做自動識別。

識別 PCI 的方法,就是讀取 /proc/bus/pci/devices 或 /sys/bus/devices/* 取得裝置所提供的 vendor(製造商)、device(裝置或晶片型號)、subvendor(再製造商)、subdevice(再製造之裝置型號),然後將這些資訊與 Linux kernel 所提供的 modules.pcimap 做比對,以得到該裝置所對應的 module name。最後,只要使用 modprobe 去載入模組就大功告成了。

比較要注意的是 modules.pcimap,如果你詳細研究過這 map 檔,應該會發現同一個 vendor:device,卻偶爾有兩種可使用的 modules。例如使用 10ec:8139 去尋找,會同時找到 8139cp 和 8139too。諸如此類的裝置非常多,所以比對 modules.pcimap 時有其規則以免發生這樣的狀況:

比對的優先順序應該是:
尋找 vendor:device 和 subvendor:subdevice 相同的專用模組。尋找 device 和 subvendor:subdevice 相同的通用模組。尋找 device 建議模組。尋找 vendor:device 標準模組。

使用 bash 完成的程式碼:
#!/bin/bash
MODULEMAP=/usr/share/frexhwd/modules.fhm

# findmodule [vendor] [device] [subvendor] [subdevice]
findmodule() {
while read VENDEV SUBVENDEV MODULE; do
if [ x"${3}${4}" = x"$SUBVENDEV" ]; then
echo $MODULE

Frexhwd 嬌小的硬體偵側程式

今年初的時候,我在 SourceForge 申請了一個 Project 叫做『Frexhwd』,這是當時我寫給這專案的一段描述:

Frexhwd is a simple and small Hardware Detection for Linux. It is written by Unix
shell(Bash) and C Language. it easy to run on small, embedded or simple system.

由這專案的名稱就可以知道,這是一個硬體偵側程式(Hardware Detection),而當初建立這專案的目標就是希望以最簡單的方式,實作硬體偵測並自動載入相對應的 Drivers。其實說到類似的功能,Debian 的 discover 與 Redhat/Fedora 的 Kudzu 都已經做得相當完整,而且在實際運作上都已經沒有什麼問題了。但如果真要說令人不滿意的地方,就是太過 fat!

discover 除了在非 Debian 系的環境中 compile 會碰到不少問題外,他的妸娜的身材倒還可以接受;而 Kudzu 從一開始就選擇 Python 當撰寫語言,根本是個錯誤。正因為 Python 的相關 Librarys 和檔案,本身就已經是個肥大的腫瘤,令使用它的 Kudzu 無法輕巧的移植到其他簡單的系統中。

最近又再次接觸到許多小型系統的研發,發現許多程式應該回歸其應用本質和單純,包山包海的結果必然會和複雜度同時產生,除了維護、移植的問題外,更有許多環境限制和浪費資源在非必要的功能,當初會建立 Frexhwd Project 也是因為有這樣的想法。

我希望 Frexhwd 是以 Shell 和 C Language 撰寫,一方面使用 Shell 可移植度高,另一方面,可以使用 C 補強 Shell 在檔案資料處理上的效能不足。不過照目前的進度來看,還未使用到 C 來撰寫任何一部份的程式,僅用到 Busybox 或 GNU 的 grep 來達成硬體模組的資料比對。

雖然遲遲沒有將 Frexhwd 的 source code 放上去,但已經有一些成果,等最近忙一段落,會將相關檔案整理好放上 SourceForge。

使用 Bash Shell 撰寫 Web CGI 程式

使用系統的 Bash Shell 來寫 CGI,這是以前做嵌入式系統時的一個 Web 應用程式解決方案,構想很酷、很有趣。當時考慮到,如果用 C 語言寫 CGI,程式會既複雜又不易維護﹝研發嵌入式系統時 Cross Compile 和繁瑣的 Debug 可是很討厭的!!﹞;若是讓 Web Server 其支援 PHP、Perl,其程式架構會太過龐大。種種因素讓我決定用 Bash 完成需要的 CGI 網站應用程式,畢竟 Bash 從面市到現在,功能越來越齊全強大了,我想應該能勝任 Web Scripts 的工作!:P

當時我先上網搜尋是否有人試過使用 Bash Shell 開發過 CGI 程式,果然有個老兄寫了一些 Bash Functions 來支援些 Web 上的操作,讓我們可以輕易使用 Bash 來寫 CGI。有興趣的人可以到 bashlib(http://bashlib.sourceforge.net/) 抓回來玩玩看。

如果你看過了這個 Bashlib ,一定發現其實它功能很陽春,只有取得 GET 傳值、表單傳值、轉向、Cookies等幾種功能。嘿嘿,這時候當然要開始惡搞這個 bashlib,我改寫並加入了一些功能,像是 Session 的支援。

自己額外亂搞新增支援 Session 的 Functions:
function init_session {
if [ ! -d /tmp/.xcdmgrsess ]; then
mkdir /tmp/.xcdmgrsess &> /dev/null
fi

SESS_ID=`cookie SESS_ID`
if [ A$SESS_ID = A"" ]; then
SESS_ID=`mkcode 30`
set_cookie SESS_ID $SESS_ID
touch /tmp/.xcdmgrsess/$SESS_ID
else
if [ -f /tmp/.xcdmgrsess/$SESS_ID ]; then
while read SESSLINE; do
eval "export 'SESSION_${SESSLINE}'"
done < /tmp/.xcdmgrsess/$SESS_ID
else
touch…

有趣的邏輯問題:是誰在說謊

開心的是期中考接近尾聲,而且今天也是我的生日,更開心的是老天爺待我很好,放我一天假沒給我排考。今天,在網路上逛啊逛,看到了一些判斷說謊的邏輯問題,雖然之前就曾看過,但不管再看多少遍都還是覺得很有趣。也想到好幾天沒寫東西了,就貼上來讓大伙一同分享吧!準備好接受考驗了嗎? Ready? Go!

第一題:

A 說B 在說謊,B 說 C 在說謊,C 說 A、B 都在說謊。請問到底誰在說謊?



第二題:

現在審問四名竊賊嫌疑犯。已知當中有一名是竊賊,還知道這四個人不是誠實就是說謊,請根據他們回答問題的結果中,判斷誰是竊賊。

甲說:『乙沒有偷,是丁偷的。』
乙說:『我沒有偷,是丙偷的。』
丙說:『甲沒有偷,是乙偷的。』
丁說:『我沒有偷。』



解答:一:只有 B 說真話。二:乙是竊賊。

OrzMicrokernel tasks.asm 尋找工作函式註解

到目前為止,從 Orz Microkernel 運作流程來看,我們已經看過主要的程式碼了,剩下的部份就只有些零零星星的函式和各種服務程式的實作。其中最重要的就是 Orz Microkernel 自訂的 IPC 訊息中斷服務(Message Service),該服務會運用到工作處理方面的函式,所以現在先將工作相關的函式註解補齊。

程式碼和詳細註解:
;------------------------------------------------------------------------------
; 尋找工作 FindTask
;;;; 輸入值: EAX = 工作編號 ID
;;;; 返回值:若進位旗標 CF=1 則表示找不到工作,否則 EAX = 工作狀態編號,EBP = 工作狀態指標
;;;; 會影響到的暫存器:EAX, ECX, ESI, EBP

FindTask:
mov ecx, [tasksCount] ; 設 ECX 為工作總數量
jecxz FindTask1 ; 若 ECX 為零,則跳到 FindTask1

mov esi, tasksList ; 設 ESI 為工作清單的記憶體位址

FindTask0:
movzx ebp, BYTE [esi] ; 從 ESI 取 2 Bytes(工作編號)到 EBP
imul ebp, s_task.msize ; EBP = EBP x s_task.msize
add ebp, tasks ; EBP = EBP + 工作狀態記錄所在記憶體位址

cmp eax, [ebp + s_task.taskID] ; 若 EAX = s_task.taskID 則零值旗標 ZF = 0
jz FindTask2 ; 若零值旗標 ZF = 0 則跳到 FindTask2

inc esi ; ESI 加一
loop FindTask0 ; 迴圈 ECX 次,繼續尋找工作

FindTask1:
s…

Orz 天殺、惡搞的 Microkernel

昨天在 IRC 上與 Jserv 有談到一點 Orz Microkernel 的問題,因為在註解的過程中,我碰到不少挫折。內容談到 Orz Microkernel 本來就是一個玩具,當初被寫出來就只是 Just Fun!,所以裡面常會出現 0x12345678 這種奇怪沒道理的定義,更有許多 Magic Code 和惡搞的陷阱,像是對目前核心沒意義的偏移之類的,這部份讓我真的被玩弄了,有強烈 Orz 的感覺﹝Jserv 成功了!囧﹞。

雖然這些惡搞的 Code 令我傻眼,但一一去發現它也不失為一個好的休閒活動﹝笑﹞! Jserv這次有說到,因為聽說真的有大專院校的學生在研究 Orz Microkernel,所以打算在下一版的 Orz Microkernel ,做精簡化、優化等等的動作,並且藉此拿掉惡搞東西,可能還會加入 GUI、Function call 等東西進去,想必許多研究 Orz Microkernel的人應該也跟我一樣看到很多傻眼的 Code 吧!!

好像要遲到了,該準備去上課囉!我是個很混的大學生,好像讀書都沒讀 Orz Microkernel 的麼的認真說。:)

被誤解的可悲稱號:電腦高手

在你心中,所謂的『電腦高手』是怎麼樣的呢?會 DIY 組裝電腦?了解硬體行情?灌 Windows 作業系統?懂得如何處理各種商業軟體的問題?還是會寫程式?救中毒或壞掉硬碟內的資料?更或是會入侵、從網路偷別人隱私?我自認不是什麼電腦高手,充其量只是朋友抬舉,電腦方面的接觸只是兼職的工讀,但常聽到很多人的話令我不知如何是好。

『某某某電腦很強,要買什麼硬體比較划算,問他就好啦!』

就是這簡短的一句話,讓我有勤練十年功而手腳筋全斷的感覺,如果說知道硬體的價格是要當電腦高手的必要條件,那我想電腦賣場中的採購、會計、業務員是天底下最厲害的武林至尊了。

『怎麼會?你電腦不是很厲害,一定知道吧!?』

大家都知道,微軟的作業系統最令人無奈的問題,就是從早期的 Always 藍色死當,到後來的『程式關閉,請洽...』,再到現在的『程式無回應』。說無奈是因為我們根本無從得知,為什麼程式或系統會突然死掉,或是某些商業軟體在設計上有什麼暇疵;還有最重要的是,微軟系的病毒嚴重肆虐,已經讓人不想再去了解病毒的變化,能殺且殺,不能殺重灌便算。還有 Office 的操作,各種軟體的使用方法,都是常見的問題,多到數不清。

但總有人會以無辜的電腦用戶自居,向人問種種莫名的狀況,如果你回應他們說『不知道』,他們總是說:『怎麼會?你電腦不是很厲害,一定知道吧!?』。哪怕有人真有閒功夫,想盡辦法去查明過去所有的問題,也是惘然,因為在這時代,軟體每天都有更新改動,病毒每日都遵行達爾文理論。我們又哪裡有這麼多時間去一一了解呢?他們弄得好像我們如某漫畫裡的主角一般,什麼東西都會駕駛一樣。

『你會不會寫遊戲外掛?會不會寫某某遊戲?會不會自己寫一個某某軟體,然後就可以賺錢了。』

不難察覺講出這些詞的人,是完全不懂電腦方面技術的人,因此聽者多半是不太計較的。但是,他們其實有一定程度的汙辱人而不自知。為什麼這樣說?因為,會講出這些話的人,都把玩電腦很厲害和電腦技術很厲害劃為等號,絲毫無所尊重辛苦的求知者,在他們心理,只要是和電腦有關的人都是『玩電腦的』。

玩電腦很厲害只要多當孝子買東買西,多砸些時間看不明信件、安裝莫名軟體然後中毒、重灌系統就能達到一等一的水準;而真正電腦技術很厲害的人,不但要每天看書看文件,還要日夜鑽研實作各種技術、新想法,並想盡辦法吸收所有日新月異的資訊,廢寢忘食。這兩種人的能力和努力相差十萬八千里,辛苦更相差何止…

OrzMicrokernel irq_handlers.asm IRQ處理和操作系統計時器 IRQ0 的函式註解

irq_handlers.asm 是 Orz Microkernel 用來處理 IRQ 的函式檔案,裡面有著處理所有 IRQ 的程式碼。之前工作排程器的部份有提到,定時切換工作是靠 IRQ0 的系統計時器達成的,其原理是當工作被賦予執行權時,同時也被授權了能佔用 CPU 的時間長度,接著,再靠著系統計時器的功能倒數計時。最後,該工作能佔用 CPU 的時間被用完,系統計時器就會如同鬧鐘響起一般,去呼叫 tasks.asm 的 Schedule 準備切換到下一個工作行程。

程式碼和詳細註解:
;------------------------------------------------------------------------
; IRQ 是處理硬體中斷請求的通道,硬體可透過 IRQ 要求 CPU 產生中斷,以處理硬體的
; 相關操作。
;
; IRQ 在中斷(INT)的編號定義:
; 08 Hardware IRQ0 System Timer
; 09 Hardware IRQ1 Keyboard
; 0A Hardware IRQ2 Redirected
; 0B Hardware IRQ3 Serial Comms. COM2/COM4
; 0C Hardware IRQ4 Serial Comms. COM1/COM3
; 0D Hardware IRQ5 Reserved/Sound Card
; 0E Hardware IRQ6 Floppy Disk Controller
; 0F Hardware IRQ7 Parallel Comms.
; 70 Hardware IRQ8 Real Time Clock
; 71 Hardware IRQ9 Redirected IRQ2
; 72 Hardware IRQ10 Reserved
; 73 Hardware IRQ11 Reserved
; 74 Hardware IRQ12 PS/2 Mouse
; 75 Hardware IRQ13 Math's Co-Processor
; …

OrzMicrokernel tasks.asm 工作排程器的切換執行權函式註解

工作新增、載入後,一切都準備就緒了,main.asm 最後一個任務,就是讓作業系統的心臟:『工作排程器』開始跳動,使所有工作能夠生生不息的運轉。Orz Microkernel 利用了 Schedule 這個 Function 切換到工作清單中的下一個工作,並利用 IRQ_0 的計時器,每一定單位時間就切換一次,使所有工作如同同時執行一般。

原始程式碼和詳細註解:
;--------------------------------------------------------------------------
; Scheduler 工作排程器:
; 多工的實作原理是讓所有的工作行程,依序輪流切換佔用 CPU 的運算能力。
; 由於每個工作佔用 CPU 的時間極小,因此近乎同時所有工作同時執行一般。
;
; Schedule: 是用來切換到下一個工作,並讓其佔用 CPU 的函式。在 main.asm 中呼叫後,
; 就會設定 taskRunningTime 工作執行的時間長度,而在 irq_handlers.asm 中
; 的 IRQ_0 計時器,就會開始依照 taskRunningTime 定時轉換到下一個工作。

tx_NoMoreTasks db "No more tasks",0 ; 設定沒有工作的訊息字串

Schedule:
mov eax, [tasksCount] ; 設 EAX 為目前工作數量
and eax, eax ; 若工作數量為零則設定零值旗標 ZF = 1
jnz Schedule0 ; 若旗標 ZF = 0 則跳到 Schedule0

mov esi, tx_NoMoreTasks ; 在 ESI 寫入沒有工作的訊息字串
jmp GpFault ; 輸出訊息

Schedule0:
mov eax, [currentTaskN] ; 設 EAX = currentTaskN
inc eax …