[聲明:歡迎轉載,轉載請注明出自CU ACCESSORY
}
為什麼要這樣設計呢?因為LINUX的設計目標之一就是應用於服務器。這種情況下,一個SERVICE可能會啟動很多進程(線程)來服務不同的CLIENT. 所以FORK設計成快速復制父進程。子進程直接使用父親的地址空間,只有子進程加載一個新的可執行文件的時候才創建自己的地址空間。
這樣節省了創建地址空間這個龐大的開銷,使得LINUX的進程創建十分快。不過實際上,這裡的進程相對於WINDOWS中的線程,所以同WINDOWS中的線程創建相比,二者的開銷應該差不多。
那麼如何才能讓新的進程加載一個可執行文件呢,這時就要用execv以及相關函數了。所以LINUX中,代替CreateProcess()的函數是fork+execv
3、文件格式 PE VS ELF
WINDOWS中的可執行文件格式是PE。到了LINUX就變成了ELF。2者有相似的地方,比如都分成幾個SECTION,包含代碼段,數據段等。但是2個又不一樣。使得從一個轉到另外一個的人不得不重新學習下。有點象在國內開慣了車的人,到了香港或者英國開車,雖然也是4個輪子一個方向盤,但是一個靠左行駛,一個靠右。總是需要些時間來習慣。
那麼為啥LINUX不能和WINDOWS用同樣的文件格式呢?我覺得可能的原因有幾個。首先可能是2個差不多同時在設計的,彼此不知道對方的存在。所以也沒法一方壓倒一方。另外一個可能的原因是PE格式最開始還是保密的(後來MS公開了PE的SPEC),所以即使LINUX想直接用PE都不行。
順便說下,MS OFFICE 的文檔格式以前也是保密的,直到最近(好像是2008年)才公開。希望這可以使得OPEN OFFICE的開發順利很多。
4、內核API:固定 VS 非固定
WINDOWS內核有一套固定的API,而且向後兼容。這使得WINDOWS 驅動的開發人員在不同版本之間移植時變得很容易。比如我用WDM (WINDOWS DEVICE MODEL) 開發一個驅動,最多改下編譯選項就可以在WIN 98, 2K, XP, 2003 下使用。VISTA 我覺得也許都可以。
而LINUX沒有固定的內核API。2.4版本的內核模塊在2.6幾乎很大可能是不能兼容的。要移植的話,不只是改個編譯選項,而是要改一堆的頭文件和實現文件等。而麻煩的是,即使都是2.6內核,不同的小版本之間也有些不同。如果你的內核模塊剛好用到了變化的部分,那麼也只好重新學習,然後改自己的頭文件或者實現文件了。
固定內核API的好處是兼容性好,壞處是包袱比較大,不得不隨時支持老的,也許是過時的接口。比如WINDOWS內核裡有WDM 一套API, 但是又有網卡專用的 NDIS 一套API. 實際上2套API的很多設計目標是重合的。那麼為什麼有2個呢?因為NDIS是先出來的,為了兼容性,一定要支持。而NDIS又只針對網卡,所以又出來了WDM。
不固定API的壞處是升級很麻煩,外圍的內核模塊維護者很辛苦。好處是可以隨時采用更新的設計。
5. WINDOWS與LINUX中的中斷處理比較
5.1不同之處:
在WINDOWS中,有一個IRQL (注意不是IRQ)的概念。最早的時候,我以為是CPU設計裡就包括了這個東東。後來看INTEL CPU手冊,發現似乎沒有。最近又看了一遍WINDOWS INTERALS 4TH。感覺這個東西應該是包括在PIC OR APIC裡面的(關於APIC,可以看我以前的帖子)。對於X86-32,硬件設備的IRQ於IRQL之間的關系是:IRQL= 27-IRQ。引入IRQL的動機似乎是這樣的:當CPU運行在低IRQL時,如果來了一個高IRQL對應的中斷,那麼低的中斷的ISR是會被高的ISR搶過去的。就是說低的ISR又被一個更高級的ISR中斷了。這樣的好處是優先級高的ISR可以更快的得到響應。
另外,在具體實現中,由於操作PIC OR APCI改IRQL是比較費時的,所以WINDOWS是盡量不去直接操作硬件,而是等到萬不得已的時候才改。
在LINUX中,似乎沒有類似IRQL這樣的觀念。就我目前看過的書和代碼來看,LINUX中的ISR或者是KERNLE最多是操作下CPU上的中斷標志位(IF)來開啟或者關閉中斷。也就是說,要麼中斷全開,要麼全關。
從這一點來看,LINUX在這部分的設計上比WINDOWS簡單。
5.2 相似之處:
WINDOWS和LINUX似乎都把中斷分成了2部分。在LINUX中叫ISR(還是其他?)和BOTTOM HALF。而WINODWS中,DPC(Deferred Procedure Calls)和APC(Asynchronous Procedure Calls)就非常類似BOTTOM HALF。二者把中斷分成兩部分的動機是差不多的。都是為了把ISR搞得越快越好。LINUX中,在ISR裡一般關中斷,所以時間太長的話,其他中斷就得不到響應。WINDOWS中,ISR跑在一個很高的IRQL裡面,同樣會阻塞其他IRQL比較低的任務。
LINUX中的BOTTOM HALF 又可以分為TASKLET 和SOFIRQ。二者的主要區別是復雜度和並發性(CONCURRENCY)。下面COPY自<UNDERSTANDING LINUX NETWORK INTERNALS>一書。
Tasklet: Only one instance of each tasklet can run at any time. Different tasklets can run concurrently on different CPUs.
Softirq: Only one instance of each softirq can run at the same time on a CPU. However, the same softirq can run on different CPUs concurrentlyOnly one instance of each softirq can run at the same time on a CPU. However, the same softirq can run on different CPUs concurrently.
WINDOWS中的DPC有點類似TASKLET和SOFTIRQ。 DPC是系統范圍內的,並且運行在DPC IRQL。是一個類似中斷上下文的環境(INTERRUPT CONTEXT)。APC和DPC的區別是運行在更低級別的APC IRQL。另外,APC是針對每一個線程的。執行在某個線程環境中。主要目的也是把一部分事情放到以後去執行。APC又分為KERNEL APC 和USER APC。APC這個觀念在LINUX中似乎沒有類似的?至少我還沒想到。
5.3 參考文獻:
1. WINDOWS INTERALS 4TH
2. UNDERSTANDING LINUX NETWORK INTERNALS, 2005
UNICODE VS ASCII