2007年5月29日 星期二

User mode vs. Kernel mode

這是一篇關於OS(作業系統)的筆記,在這裡我將用Linux kernel作例子,解釋OS中Kernel/User mode的概念,由於作者才疏學淺,若有闕漏以及謬誤,敬請指正,感謝。

在許多電腦的硬體架構中,為了不讓程式任意存取任何資源(例如隨意存取記憶體),大部分的CPU架構都支援Kernel mode與User mode兩種執行模式,當然這種模式也得要OS有相關實作配合才有作用,像DOS就沒有Kernel/User mode的分別,所有以DOS執行的程式都可對任意資源執行任何行為,所以DOS上的病毒才能那麼囂張,動不動就格式化硬碟。

一般來說,應用程式是在User mode中執行程式,普通的數值計算或變數指派都可以在這模式完成,但是若要執行一些危及系統安全的指令(例如對磁碟機寫出資料),而這些指令是不準在User mode中執行的,強要執行那些特殊指令只會讓系統給你一個錯誤訊息而已,應用程式必須呼叫一些OS定義好的函式才能達成那些功能,例如printf(),這些OS事先定義好的函式我們稱為system call(系統呼叫)。

當應用程式執行了system call,並不是傻傻地讓應用程式想做甚麼就做甚麼,他們首先會嚴密地檢查這個呼叫的應用程式的權限以及操作的內容(是否讀取不屬於自己的記憶體範圍,是否讀寫沒有權限讀寫的檔案,是否想把資料往錯誤的裝置送過去......),若是有任何錯誤,system call將會停止執行並回傳一個錯誤代號,讓應用程式知道自己錯在何處。相反地一切檢查都沒問題,system call將會通知CPU進入Kernel mode,並依照應用程式送過來的參數執行特權指令。當特權指令執行完畢,system call將會通知CPU返回User mode,並回到應用程式中。

Kernel mode/User mode架構是非常普遍的執行模式,幾乎可以在任何機器上看到這套架構,從電腦到機上盒,刷卡機等等電子商品,為了保護某些特別的指令不被搞不清楚狀況的程式開發者亂玩,OS開發者通常藉由定義system call告訴開發者們,哪些行為必須經過OS的過濾才能執行。

當然Linux等Open source kernel的開發者可以自行定義並增加system call的數量,豐富OS與應用程式的溝通介面,不過這種修改得經過非常小心的計畫與測試,因為在system call裡面執行的程式若是有錯,很可能讓整個OS崩潰(死機)!例如許多沒有Open source的驅動程式(xVidia,ATx之類的顯示卡),由於Kernel的開發者無從得知那些驅動程式的演算法,所以也無法保證那些驅動程式會不會讓Kernel執行到一半掛掉。

事實上,所有第三方撰寫的驅動程式都會有這種問題,Windows常常被人臭罵有時候真的是無辜的,一切都是因為寫驅動程式的第三方公司功力太爛,寫出品質低落的驅動程式讓Windows壞到掛掉,微軟Windows小組也是滿腹苦水(在此並沒有袒護微軟的意思,只是陳述事實)。

2 則留言:

匿名 提到...

關於Developer修改system call,那developer需要有CPU硬體方面的知識嗎?還是只要懂OS就好?

Peachwa & Neversay 提到...

Developer不需要CPU知識,但是通常要懂一些assemble 知識,因為有些程式區段為了加速,通常會用assemble code來寫,而不是c.