LINUX 核心的型別(轉)
LINUX 核心的型別(轉)[@more@]解決複雜性的所有方法都基於一個基本原理:問題分解和各個擊破。也就是說,都是把大
型的、難以解決的問題(或系統)分解成一定數量的複雜度較低的子問題(或子系統),
再根據需要重複這一過程直到每一部分都小到可以解決為止,而各種方法只是這種原理的
一些不同運用而已。
電腦科學中有三種經典的方法比較適合於構建大型系統(我首先必須說明的是,這些定
義都是經過我深思熟慮的討論物件)。
1) 層次(Layer)—將解決方案分解成若干部分,在這些部分中存在一個問題域的最底層
,它為上層的抽象層次較高的工作提供基礎。較高層建立在其低層基礎之上。OSI和
TCP/IP協議堆疊是眾所周知的層次化軟體設計的成功的例子。作業系統設計的層次化解決
方案可能會包含一個可以直接和硬體通訊的層次,然後在其上提供為更高層提供抽象支援
的層次。這樣更高層就可以對磁碟、網路卡等硬體進行訪問,而並不需要了解這些裝置的具
體細節。
層次化設計的一個特徵是要逐步構建符號集(vocabulary)。隨著層次的升高,符號集的
功能將越來越強大。層次化設計的另外一個特徵是完全可以在對其上下層透明的條件下替
換某一層次。在最理想的情況下,移植層次化的作業系統只需要重寫最底層的程式碼。純層
次化模型實現的執行速度可能會很慢,因為高層必須(間接的)透過呼叫一系列連續的低
層才能處理完自己的任務—N層呼叫N-1層,N-1層呼叫N-2層,等等,直到實際的工作在0
層被處理完成。接著,結果當然是透過同樣的路徑反向傳遞回來。因此,層次化設計通常
會包含對某些高層直接和某些低層通訊的支援;這樣雖然提高了速度,但是卻使得各個層
次的替換工作更加困難(因為不止一個高層會直接依賴於這個你所希望進行替換的層次)
。
* 模組(Module)—模組將具體的一部分功能塊隱藏在抽象的介面背後。模組的最大特點
是將介面和其實現分離開來,這樣就能夠保證一個模組可以在不影響其他模組的情況下進
行改變。這樣也將模組之間的依賴關係僅僅限定於介面。模組的範圍是試圖反映求解域內
一些方面的自然的概念性界限。純模組化的作業系統因而就可能有一個磁碟子系統模組,
一個記憶體管理子系統模組,等等。純模組化和純層次化的作業系統之間的主要區別是,一
個可以由其他模組自由呼叫,模組間沒有上層和下層的概念(從這個意義上來說,模組是
廣義的層次。按照純粹的觀點,層次是最多可供一個其它模組呼叫的模組,這個模組也就
是它的直接上層模組)。
* 物件(Object)—物件和模組不同,因為對於初學者來說它們具有不同的問題考慮方式
,實現的方法也可能各自獨立。但是,就我們當前的目的來說,物件不過是結構化使用模
塊的方法。元件(component)作為物件思想的進一步改進,目前還沒有在作業系統設計
中廣泛使用。即便如此(按照我們的觀點),我們也沒有足夠的理由將其和模組劃分在不
同的範疇中。
圖3-1強調了核心的層次化的檢視,而且是體系結構無關層次位於體系結構相關層次之上
(更為精確的檢視是在頂層增加一個附加的體系結構相關的層次。這是因為系統呼叫介面
位於應用程式和核心之間,而且是體系結構相關的)。圖3-2著重強調了更加模組化的內
核檢視。
從合理的表述層次上看,這兩種觀點都是正確的。但也可以說這兩種觀點都是錯誤的。我
可以用大量的圖片向你證明核心是遵從所有你所能夠指出的設計原則集合的,因為它就是
從眾多思想中抽取出來的。簡單說來,事實是Linux核心既不是嚴格層次化的,也不是嚴
格模組化的,也不是嚴格意義上的任何型別,而是以實用為主要依據的(實際上,如果要
用一個詞來概括Linux從設計到實現的所有特點,那麼實用就是最確切的)。也許最保守
的觀點是核心的實現是模組化的,雖然這些模組有時會為了追求速度而有意跨越模組的界
限。
這樣,Linux的設計同時兼顧了理論和實際。Linux並沒有忽視設計方法;相反,在Linux
的開發基本思想中,設計方法的作用就像是編譯器:它是完成工作的有力工具。選擇一個
基本的設計原則(例如物件)並完全使用這種原則,不允許有任何例外,這對於測試該原
則的限制,或者構建以說明這些方法為目的的教學系統來說都是一個不錯的方法。但是如
果要用它來達到Linux的設計目標則會引起許多問題。而且Linux的設計目標中也並不包括
要使核心成為一個完全純化的系統。Linux開發者為了達到設計目標寧願違背妨礙目標實
現的原則。
實際上,如果對於Linux來說是正確的,那麼它們對於所有最成功的設計來說都是正確的
。最成功、應用最廣泛的實際系統必然是實用的系統。有些開發人員試圖尋找功能強大的
可以解決所有問題的特殊方法。他們一旦找到了這種方法,所有的問題就都迎刃而解了。
像Linux核心一樣的成功設計通常需要為系統的不同部分和描述上的不同層次使用不同的
方法。這樣做的結果可能不是很清晰,也不是很純粹,但是這種混合產物比同等功能的純
粹系統要強大而且優秀得多。
Linux大部分都是單核心的
作業系統核心可能是微核心,也可能是單核心(後者有時稱之為單核心Macrokernel)。
按照類似封裝的形式,這些術語定義如下:
* 微核心(microkernel)—在微核心中,大部分核心都作為獨立的程式在特權狀態下運
行,它們透過訊息傳遞進行通訊。在典型情況下,每個概念模組都有一個程式。因此,如
果在設計中有一個系統呼叫模組,那麼就必然有一個相應的程式來接收系統呼叫,並和能
夠執行系統呼叫的其他程式(或模組)通訊以完成所需任務。
在這些設計中,微核心部分經常只不過是一個訊息轉發站:當系統呼叫模組要給檔案系統
模組傳送訊息時,訊息直接透過核心轉發。這種方式有助於實現模組間的隔離(某些時候
,模組也可以直接給其他模組傳遞訊息)。在一些微核心的設計中,更多的功能,如I/O
等,也都被封裝在核心中了。但是最根本的思想還是要保持微核心儘量小,這樣只需要把
微核心本身進行移植就可以完成將整個核心移植到新的平臺上。其他模組都只依賴於微內
核或其他模組,並不直接直接依賴硬體。
微核心設計的一個優點是在不影響系統其他部分的情況下,用更高效的實現代替現有檔案
系統模組將會更加容易。我們甚至可以在系統執行時將開發出的新系統模組或者需要替換
現有模組的模組直接而迅速地加入系統。另外一個優點是不需要的模組將不會被載入到內
存中,因此,微核心就可以更有效地利用記憶體。
* 單核心(monolithic kernel)—單核心是一個很大的程式。它的內部又可以被分為若
幹模組(或者是層次或其他)。但是在執行的時候,它是一個獨立的二進位制大映象。其模
塊間的通訊是透過直接呼叫其他模組中的函式實現的,而不是訊息傳遞。
單核心的支持者聲稱微核心的訊息傳遞開銷引起了效率的損失。微核心的支持者則認為因
此而增加的核心設計的靈活性和可維護性可以彌補任何損失。
我並不想討論這些問題,但必須說明非常有趣的一點是,這種爭論經常會令人想到前幾年
CPU領域中RISC和CISC的鬥爭。現代成功的CPU設計中包含了所有這兩種技術,就像Linux
核心是微核心和單核心的混合產物一樣。Linux核心基本上是單一的,但是它並不是一個
純粹的整合核心。前面一章所介紹的核心模組系統將微核心的許多優點引入到Linux的單
核心設計中。(順便提一下,我考慮過一種有趣的情況,就是Linux的核心模組系統可以
將系統核心轉化成為簡單的不傳遞訊息的微核心設計。雖然我並不贊成,但是它仍然是一
個有趣的想法。)
為什麼Linux必然是單核心的呢?一個方面是歷史的原因:在Linus的觀點看來,透過把內
核以單一的方式進行組織並在最初始的空間中執行是相當容易的事情。這種決策避免了有
關訊息傳遞體系結構、計算模組裝載方式等相關工作。(核心模組系統在隨後的幾年中又
進行了不斷地改進。)
另外一個原因是充足的開發時間的結果。Linux既沒有開發時間的限制,也沒有來自於市
場壓力的發行進度。 所有的限制只有並不過分的對核心的修改與擴充。核心的單一設計
在內部實現了充分的模組化,在這種條件下的修改或增加都並不怎麼困難。而且問題還在
於沒有必要為了追求尚未證實的可維護性的微小增長而重寫Linux的核心(Linus曾多次特
彆強調了如下的觀點:為了這點利益而損耗速度是不值得的)。後面章節中將詳細討論充
足開發時間的效果。
如果Linux是純微核心設計,那麼向其他體系結構上的移植將會比較容易。實際上,有一
些微核心,如Mach微核心,就已經成功地證明了這種可移植性的優點。實際的情況是,
Linux核心的移植雖然不是很簡單,但也絕不是不可能的:大約的數字是,向一個全新的
體系結構上的典型的移植工作需要30 000到60 000行程式碼,再加上不到20 000行的驅動程
序程式碼(並不是所有的移植都需要新的驅動程式程式碼)。粗略計算一下,一個典型的移植
大約平均需要50 000行程式碼。這對於一個程式設計師或者最多一個程式小組來說是力所能及的
,可以在一年之內完成。雖然這比微核心的移植需要更多的程式碼,但是Linux的支持者將
會提出,這樣的Linux核心移植版本比微核心更能夠有效地利用底層硬體,因而移植過程
中的額外工作是能夠從系統效能的提高上得到補償的。
這種特殊設計的權衡也不是很輕鬆就可以達到的,單核心的實現策略公然違背了傳統的看
法,後者認為微核心是未來發展的趨勢。但是由於單一模式(大部分情況下)在Linux中
執行狀態良好,而且核心移植相對來說比較困難,但沒有明顯地阻礙程式設計師團體的工作,
他們已經成功地把核心移植到了現存的大部分實際系統中,更不用說類似掌上型電腦了。
只要Linux的眾多特點仍然值得移植,新的移植版本就會不斷湧現。
型的、難以解決的問題(或系統)分解成一定數量的複雜度較低的子問題(或子系統),
再根據需要重複這一過程直到每一部分都小到可以解決為止,而各種方法只是這種原理的
一些不同運用而已。
電腦科學中有三種經典的方法比較適合於構建大型系統(我首先必須說明的是,這些定
義都是經過我深思熟慮的討論物件)。
1) 層次(Layer)—將解決方案分解成若干部分,在這些部分中存在一個問題域的最底層
,它為上層的抽象層次較高的工作提供基礎。較高層建立在其低層基礎之上。OSI和
TCP/IP協議堆疊是眾所周知的層次化軟體設計的成功的例子。作業系統設計的層次化解決
方案可能會包含一個可以直接和硬體通訊的層次,然後在其上提供為更高層提供抽象支援
的層次。這樣更高層就可以對磁碟、網路卡等硬體進行訪問,而並不需要了解這些裝置的具
體細節。
層次化設計的一個特徵是要逐步構建符號集(vocabulary)。隨著層次的升高,符號集的
功能將越來越強大。層次化設計的另外一個特徵是完全可以在對其上下層透明的條件下替
換某一層次。在最理想的情況下,移植層次化的作業系統只需要重寫最底層的程式碼。純層
次化模型實現的執行速度可能會很慢,因為高層必須(間接的)透過呼叫一系列連續的低
層才能處理完自己的任務—N層呼叫N-1層,N-1層呼叫N-2層,等等,直到實際的工作在0
層被處理完成。接著,結果當然是透過同樣的路徑反向傳遞回來。因此,層次化設計通常
會包含對某些高層直接和某些低層通訊的支援;這樣雖然提高了速度,但是卻使得各個層
次的替換工作更加困難(因為不止一個高層會直接依賴於這個你所希望進行替換的層次)
。
* 模組(Module)—模組將具體的一部分功能塊隱藏在抽象的介面背後。模組的最大特點
是將介面和其實現分離開來,這樣就能夠保證一個模組可以在不影響其他模組的情況下進
行改變。這樣也將模組之間的依賴關係僅僅限定於介面。模組的範圍是試圖反映求解域內
一些方面的自然的概念性界限。純模組化的作業系統因而就可能有一個磁碟子系統模組,
一個記憶體管理子系統模組,等等。純模組化和純層次化的作業系統之間的主要區別是,一
個可以由其他模組自由呼叫,模組間沒有上層和下層的概念(從這個意義上來說,模組是
廣義的層次。按照純粹的觀點,層次是最多可供一個其它模組呼叫的模組,這個模組也就
是它的直接上層模組)。
* 物件(Object)—物件和模組不同,因為對於初學者來說它們具有不同的問題考慮方式
,實現的方法也可能各自獨立。但是,就我們當前的目的來說,物件不過是結構化使用模
塊的方法。元件(component)作為物件思想的進一步改進,目前還沒有在作業系統設計
中廣泛使用。即便如此(按照我們的觀點),我們也沒有足夠的理由將其和模組劃分在不
同的範疇中。
圖3-1強調了核心的層次化的檢視,而且是體系結構無關層次位於體系結構相關層次之上
(更為精確的檢視是在頂層增加一個附加的體系結構相關的層次。這是因為系統呼叫介面
位於應用程式和核心之間,而且是體系結構相關的)。圖3-2著重強調了更加模組化的內
核檢視。
從合理的表述層次上看,這兩種觀點都是正確的。但也可以說這兩種觀點都是錯誤的。我
可以用大量的圖片向你證明核心是遵從所有你所能夠指出的設計原則集合的,因為它就是
從眾多思想中抽取出來的。簡單說來,事實是Linux核心既不是嚴格層次化的,也不是嚴
格模組化的,也不是嚴格意義上的任何型別,而是以實用為主要依據的(實際上,如果要
用一個詞來概括Linux從設計到實現的所有特點,那麼實用就是最確切的)。也許最保守
的觀點是核心的實現是模組化的,雖然這些模組有時會為了追求速度而有意跨越模組的界
限。
這樣,Linux的設計同時兼顧了理論和實際。Linux並沒有忽視設計方法;相反,在Linux
的開發基本思想中,設計方法的作用就像是編譯器:它是完成工作的有力工具。選擇一個
基本的設計原則(例如物件)並完全使用這種原則,不允許有任何例外,這對於測試該原
則的限制,或者構建以說明這些方法為目的的教學系統來說都是一個不錯的方法。但是如
果要用它來達到Linux的設計目標則會引起許多問題。而且Linux的設計目標中也並不包括
要使核心成為一個完全純化的系統。Linux開發者為了達到設計目標寧願違背妨礙目標實
現的原則。
實際上,如果對於Linux來說是正確的,那麼它們對於所有最成功的設計來說都是正確的
。最成功、應用最廣泛的實際系統必然是實用的系統。有些開發人員試圖尋找功能強大的
可以解決所有問題的特殊方法。他們一旦找到了這種方法,所有的問題就都迎刃而解了。
像Linux核心一樣的成功設計通常需要為系統的不同部分和描述上的不同層次使用不同的
方法。這樣做的結果可能不是很清晰,也不是很純粹,但是這種混合產物比同等功能的純
粹系統要強大而且優秀得多。
Linux大部分都是單核心的
作業系統核心可能是微核心,也可能是單核心(後者有時稱之為單核心Macrokernel)。
按照類似封裝的形式,這些術語定義如下:
* 微核心(microkernel)—在微核心中,大部分核心都作為獨立的程式在特權狀態下運
行,它們透過訊息傳遞進行通訊。在典型情況下,每個概念模組都有一個程式。因此,如
果在設計中有一個系統呼叫模組,那麼就必然有一個相應的程式來接收系統呼叫,並和能
夠執行系統呼叫的其他程式(或模組)通訊以完成所需任務。
在這些設計中,微核心部分經常只不過是一個訊息轉發站:當系統呼叫模組要給檔案系統
模組傳送訊息時,訊息直接透過核心轉發。這種方式有助於實現模組間的隔離(某些時候
,模組也可以直接給其他模組傳遞訊息)。在一些微核心的設計中,更多的功能,如I/O
等,也都被封裝在核心中了。但是最根本的思想還是要保持微核心儘量小,這樣只需要把
微核心本身進行移植就可以完成將整個核心移植到新的平臺上。其他模組都只依賴於微內
核或其他模組,並不直接直接依賴硬體。
微核心設計的一個優點是在不影響系統其他部分的情況下,用更高效的實現代替現有檔案
系統模組將會更加容易。我們甚至可以在系統執行時將開發出的新系統模組或者需要替換
現有模組的模組直接而迅速地加入系統。另外一個優點是不需要的模組將不會被載入到內
存中,因此,微核心就可以更有效地利用記憶體。
* 單核心(monolithic kernel)—單核心是一個很大的程式。它的內部又可以被分為若
幹模組(或者是層次或其他)。但是在執行的時候,它是一個獨立的二進位制大映象。其模
塊間的通訊是透過直接呼叫其他模組中的函式實現的,而不是訊息傳遞。
單核心的支持者聲稱微核心的訊息傳遞開銷引起了效率的損失。微核心的支持者則認為因
此而增加的核心設計的靈活性和可維護性可以彌補任何損失。
我並不想討論這些問題,但必須說明非常有趣的一點是,這種爭論經常會令人想到前幾年
CPU領域中RISC和CISC的鬥爭。現代成功的CPU設計中包含了所有這兩種技術,就像Linux
核心是微核心和單核心的混合產物一樣。Linux核心基本上是單一的,但是它並不是一個
純粹的整合核心。前面一章所介紹的核心模組系統將微核心的許多優點引入到Linux的單
核心設計中。(順便提一下,我考慮過一種有趣的情況,就是Linux的核心模組系統可以
將系統核心轉化成為簡單的不傳遞訊息的微核心設計。雖然我並不贊成,但是它仍然是一
個有趣的想法。)
為什麼Linux必然是單核心的呢?一個方面是歷史的原因:在Linus的觀點看來,透過把內
核以單一的方式進行組織並在最初始的空間中執行是相當容易的事情。這種決策避免了有
關訊息傳遞體系結構、計算模組裝載方式等相關工作。(核心模組系統在隨後的幾年中又
進行了不斷地改進。)
另外一個原因是充足的開發時間的結果。Linux既沒有開發時間的限制,也沒有來自於市
場壓力的發行進度。 所有的限制只有並不過分的對核心的修改與擴充。核心的單一設計
在內部實現了充分的模組化,在這種條件下的修改或增加都並不怎麼困難。而且問題還在
於沒有必要為了追求尚未證實的可維護性的微小增長而重寫Linux的核心(Linus曾多次特
彆強調了如下的觀點:為了這點利益而損耗速度是不值得的)。後面章節中將詳細討論充
足開發時間的效果。
如果Linux是純微核心設計,那麼向其他體系結構上的移植將會比較容易。實際上,有一
些微核心,如Mach微核心,就已經成功地證明了這種可移植性的優點。實際的情況是,
Linux核心的移植雖然不是很簡單,但也絕不是不可能的:大約的數字是,向一個全新的
體系結構上的典型的移植工作需要30 000到60 000行程式碼,再加上不到20 000行的驅動程
序程式碼(並不是所有的移植都需要新的驅動程式程式碼)。粗略計算一下,一個典型的移植
大約平均需要50 000行程式碼。這對於一個程式設計師或者最多一個程式小組來說是力所能及的
,可以在一年之內完成。雖然這比微核心的移植需要更多的程式碼,但是Linux的支持者將
會提出,這樣的Linux核心移植版本比微核心更能夠有效地利用底層硬體,因而移植過程
中的額外工作是能夠從系統效能的提高上得到補償的。
這種特殊設計的權衡也不是很輕鬆就可以達到的,單核心的實現策略公然違背了傳統的看
法,後者認為微核心是未來發展的趨勢。但是由於單一模式(大部分情況下)在Linux中
執行狀態良好,而且核心移植相對來說比較困難,但沒有明顯地阻礙程式設計師團體的工作,
他們已經成功地把核心移植到了現存的大部分實際系統中,更不用說類似掌上型電腦了。
只要Linux的眾多特點仍然值得移植,新的移植版本就會不斷湧現。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617542/viewspace-945795/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JavaScript核心概念(1):型別轉換JavaScript型別
- 加框和消框,C#型別系統的核心概念 (轉)C#型別
- java- 型別-轉換:基本型別以及包裝型別的轉換Java型別
- 在Red Hat Enterprise Linux中有什麼型別的核心?Linux型別
- Android核心和Linux核心的區別AndroidLinux
- 流程的型別(轉)型別
- Linux系統應用程式和核心模組的區別(轉)Linux
- 日期型別與String型別的轉換型別
- iOS核心動畫型別介紹iOS動畫型別
- 資料型別,型別轉換資料型別
- PHP 型別轉換&&型別強制轉換PHP型別
- java型別轉換與強制型別轉換(轉)Java型別
- C++中的向上型別轉換和向下型別轉換C++型別
- interface{} 型別的轉換型別
- golang的型別轉換Golang型別
- linux核心和windows核心的一些區別LinuxWindows
- 33 個 JavaScript 核心概念系列(二): 值型別與引用型別JavaScript型別
- RedHat Linux 9下識別和使用檔案型別(轉)RedhatLinux型別
- 型別轉換型別
- Redis 筆記(核心資料型別)Redis筆記資料型別
- Linux核心的組成部分(轉)Linux
- mysql bigint型別和datetime型別的轉換MySql型別
- 資料型別的轉換資料型別
- ORACLE的資料型別(轉)Oracle資料型別
- java中的型別轉換Java型別
- Java資料型別及型別轉換Java資料型別
- 字元型別轉換成時間型別字元型別
- Oracle Long型別轉換為Clob型別Oracle型別
- C#變數型別(1):引用型別和值型別 (轉)變數型別
- LINUX核心升級 (轉)Linux
- Linux核心分析方法(轉)Linux
- LINUX核心升級(轉)Linux
- linux 下的連線型別Linux型別
- C語言中資料型別的自動型別轉換C語言資料型別
- 主流資料庫欄位型別轉.Net型別的方法資料庫型別
- Linux 核心和 Windows 核心有什麼區別?LinuxWindows
- 用Mgaic Linux的核心和模組代替Debian的核心(轉)AILinux
- 自學java筆記I 基本型別+轉義字元+資料型別的轉換Java筆記字元資料型別