詳解Linux 2.6核心新變化(1)(轉)

worldblog發表於2007-08-10
詳解Linux 2.6核心新變化(1)(轉)[@more@]

  即將釋出的新的穩定的核心支援更多型別的處理器,並且可靠性和可擴充套件性得到了提高 ,因而將推動 Linux 得到更廣泛的應用。在這裡我們將重點介紹一些不同程度的變化,並給出部分程式碼樣例。

  Linux 核心的開發已經經歷了一個漫長的過程,最初是 Linus Torvalds 於1991年釋出的原始的0.1版本,這個版本中包括一個基本的排程器、IPC(程式間通訊)和記憶體管理演算法。而現在它已經是一個以往作業系統的實用的替代品,在市場上表現出了強大的競爭力。越來越多的政府機構和IT巨頭的注意力正在轉向 Linux。從最小的嵌入式裝置到 S/390,從手錶到大型企業伺服器,Linux 現在幾乎可以用於所有的地方。

  Linux 2.6 是 Linux 開發週期中的下一個主要版本,它包括了一些強有力的特性,這些特性旨在改進高階企業伺服器的效能和支援越來越多的嵌入式裝置(要了解更詳細的關於 Linux 2.6 對大型的、小型的以及多處理器系統支援問題的分析,請參閱參考資料一節中到 Joseph Pranevich 的“Linux 的精彩世界”的連結)。

  本文為關注 Linux 的使用者分析了 Linux 2.6 的一些重要特性,並且討論了驅動程式開發人員可能會感興趣的多方面的變化。

  Linux 2.6亮點

  無論是對於企業伺服器還是對於嵌入式系統,Linux 2.6 都是一個巨大的進步。對高階的機器來說,新特性針對的是效能改進、可擴充套件性、吞吐率,以及對 SMP 機器 NUMA 的支援。對於嵌入式領域,新增了新的體系結構和處理器型別——包括對那些沒有硬體控制的記憶體管理方案的 MMU-less 系統的支援。並且,和往常一樣,為了滿足桌面使用者群的需要,新增了一整套新的音訊和多媒體驅動程式。

  在本文中,我們分析了 Linux 2.6的一些最引人關注的特性,但是仍有很多值得關注的變化,包括增強的核心核心轉儲、快速互斥支援、改進的I/O子系統,等等,在這裡我們不能全部討論。在側欄中總結了其中一些,其餘的我們在參考資料一節中給出了連結。

  新的排程器

  2.6版本的 Linux 核心使用了由 Ingo Molnar 開發的新的排程器演算法,稱為O(1)演算法,它在高負載的情況下執行得極其出色,並且當有很多處理器時也可以很好地擴充套件。

  在2.4版本的排程器中,時間片重算演算法要求在所有的程式都用盡它們的時間片以後,它們的新時間片才會被重新計算。這樣的話在一個有很多處理器的系統中,當程式用完它們的時間片以後得等待重算(以得到新的時間片),從而導致大部分的處理器處於空閒狀態;這將影響SMP的效率。除此之外,當空閒的處理器開始執行那些時間片尚未用盡的處於等待狀態的程式(如果它們自己的處理器忙),會導致程式開始在處理器之間“跳躍”。當一個高優先順序程式或者互動式程式發生跳躍時,整個系統的效能就會受到影響。

  新的排程器解決上述問題的方法是,基於每個 CPU 來分佈時間片,並且取消了全域性同步和重算迴圈。排程器使用了兩個優先順序陣列,即活動陣列和過期陣列,可以透過指標來訪問它們。活動陣列中包含了所有對映到某個CPU而且時間片尚未用盡的任務。過期陣列中包含了一個時間片已經用盡的所有任務的有序列表。如果所有活動任務的時間片都已用盡,那麼指向這兩個陣列的指標互換,過期陣列(包含了準備執行的任務)成為活動陣列,而空的活動陣列成為包含過期任務的新陣列。陣列的索引儲存在一個64位的點陣圖中,找到最高優先順序的任務是很容易的。

  新的排程器現在不再有大的 runqueue_lock。它維持每個處理器的執行佇列/鎖機制,以使得兩個不同處理器上的兩個程式可以完全並行地休眠、喚醒和上下文切換。重算迴圈(為程式重新計算時間片)和 goodness 迴圈已經被取消,O(1)演算法用於 wakeup() 和 schedulee()。

  新排程器的主要好處包括:

  SMP效率:如果有工作需要完成,那麼所有處理器都會工作。

  等待程式:沒有程式需要長時間地等待處理器;同時,沒有程式會無端地佔用大量的CPU時間。

  SMP程式對映:程式只對映到一個CPU而且不會在CPU之間跳躍。

  優先順序:不重要的任務的優先順序低(反之亦然)。

  負載平衡:排程器會降低那些超出處理器負載能力的程式的優先順序。

  互動效能:使用新的排程器,即便是在非常高負載的情況下,系統花費很長時間來響應滑鼠點選或者鍵盤輸入的情況將不會再發生。

  核心搶佔

  核心搶佔補丁在2.5系列中就已經被打上,接下來在2.6中也會打。這將顯著地降低使用者互動式應用程式、多媒體應用程式等類似應用程式的延遲。這一特性對實時系統和嵌入式系統來說特別有用。

  2.5的核心搶佔模組的工作由 Robert Love 完成。在先前的核心版本中(包括2.4核心),不允許搶佔以核心模式執行的任務(包括透過系統呼叫進入核心模式的使用者任務),直到它們自己主動釋放 CPU。

  在核心2.6中,核心是可搶佔的。一個核心任務可以被搶佔,為的是讓重要的使用者應用程式可以繼續執行。這樣做最主要的優勢在於,可以極大地增強系統的使用者互動性,使用者將會覺得滑鼠點選和擊鍵的事件得到了更快速的響應。

  當然,不是所有的核心程式碼段都可以被搶佔。可以鎖定核心程式碼的關鍵部分,不允許搶佔。鎖定可以確保每個 CPU 的資料結構和狀態始終受到保護而不被搶佔。

  以下的程式碼片斷顯示了每個 CPU 的資料結構問題(在SMP系統中):

  清單 1. 存在核心搶佔問題的程式碼

  int arr[NR_CPUS];

arr[smp_processor_id()] = i;

    /* kernel preemption could happen here */

    j = arr[smp_processor_id()]  /* i and j are not equal as

    smp_processor_id() may not be the same */

  在這種情形下,如果在特定點發生了核心搶佔,任務將會由於重新排程而被分配到其他處理器——smp_processor_id() 將返回一個不同的值。

  這種情形應該透過鎖定來進行保護。

  FPU 模式是另外一種CPU應該被保護起來不被搶佔的情形。當核心在執行浮點指令時,FPU 狀態不被儲存。如果這時發生了搶佔,由於重新排程,FPU 狀態就會與搶佔前完全不同。所以 FPU 程式碼必須始終被鎖定,以防止核心搶佔。

  鎖定可以這樣來實現,在關鍵部分禁止搶佔,在之後再啟用搶佔。以下是在2.6核心中禁止和啟用搶佔的定義:

  preempt_enable() -- 搶佔計數器減1

  preempt_disable() -- 搶佔計數器加1

  get_cpu() -- 先後呼叫 preempt_disable() 和 smp_processor_id()

  put_cpu() -- 重新啟用preemption()

  使用這些定義,清單 1可以重寫成這樣:

  清單 2. 使用防搶佔鎖的程式碼

  int cpu, arr[NR_CPUS];

arr[get_cpu()] = i; /* disable preemption */

    j = arr[smp_processor_id()];

    /* do some critical stuff here */

    put_cpu()  /* re-enable preemption */

  注意 preempt_disable()/enable()呼叫是可以巢狀的。也就是說,preempt_disable() 可以被呼叫 n 次,只有當第 n 次 preempt_enable() 被呼叫後,搶佔才被重新啟用。

  當使用自旋鎖時,搶佔是被隱式地禁止的。例如,一個 spin_lock_irqsave() 呼叫會隱式地透過呼叫 preempt_disable() 來防止搶佔;spin_unlock_irqrestroe() 透過呼叫 preempt_enable() 來重新啟用搶佔。

  改進的執行緒模型以及對 NPTL 的支援

  在2.5核心中已經做了很多的改進執行緒效能的工作。在2.6中改進的執行緒模型仍然是由 Ingo Molnar 來完成的。它基於一個1:1的執行緒模型(一個核心執行緒對應一個使用者執行緒),包括核心內在的對新的 NPTL(Native Posix Threading Library)的支援,這個新的 NPTL 是由 Molnar 和 Ulrich Drepper 合作開發的。

  2.6核心中其他引人注目的變化 

  檔案系統

  對 ext2/ext3 檔案系統做了改進,包括對擴充套件屬性和POSIX訪問控制列表的支援。NTFS的驅動程式也已經重寫,可以支援(reentrant safe)SMP,大於4KB的簇,等等。同時2.6也支援 IBM 的 JFS(journaling file system) 和 SGI 的 XFS。

  音訊

  對桌面使用者而言,一個更令人期待的特性是稱為 ALSA(Advanced Linux Sound Architecture) 的新的 Linux 音訊體系結構,它取代了缺陷很多的舊的 OSS (Open Sound System)。新的聲音體系結構支援USB音訊和MIDI裝置,全雙工重放,等等。在桌面上播放 MP3 和其他音訊檔案再也不會像以前那樣了!

  匯流排

  SCSI/IDE子系統經過大幅度的重寫,一些驅動程式仍然處於測試階段或者收尾階段。

  電源管理

  支援 ACPI(高階電源配置管理介面,Advanced Configuration and Power Interface),用於調整 CPU(可以在不同的負載下使CPU工作於不同的時脈頻率以節電)和軟體掛起(這一特性仍在測試中)。

  聯網和IPSec

  核心中加入了對 IPSec (IP安全)的支援,因此也支援 IP 有效負載壓縮等各種 RFC。刪除了原來核心內建的HTTP伺服器 kttpd。IPSec 特性使用了核心提供的新的加密 API。這個加密API中包含了各種流行的演算法,比如 MD4,MD5 DES,等等。加入了對新的 NFSv4 (網路檔案系統)客戶機/伺服器的支援。

  使用者介面層

  2.6核心重寫了幀緩衝/控制檯層。這將意味著需要更新各種使用者空間幀緩衝工具,如 fbset 和 fbdesl。人機介面層還加入了對近乎所有可接入裝置的支援,從觸控式螢幕到盲人用的裝置,到各種各樣的滑鼠。

  執行緒操作可以提高速度;2.6核心現在可以處理任意數目的執行緒,PID最大可以到20億(IA32上)。

  另外一個變化是引入了 TLS(Thread Local Storage)系統呼叫,這個呼叫允許分配一個或多個 GDT(Global Descriptor Table)條目,作為執行緒登錄檔。每個 CPU 有一個 GDT,每個條目對應一個執行緒。這樣就可以實現一個不受建立的執行緒數限制的1:1執行緒模型(因為每一個新的核心執行緒都是為一個使用者執行緒而建立)。2.4核心中每個處理器最多隻能支援8,192個執行緒。

  系統呼叫 clone 被擴充套件,以最佳化執行緒的建立。如果 CLONE_PARENT_SETID 標誌被設定,核心會把執行緒ID儲存在一個給定的記憶體位置,如果當執行緒結束時 CLONE_CLEARID 標誌被設定,核心就會把那個記憶體位置清空。這有助於使用者級的記憶體管理去識別沒有使用的記憶體塊。同樣,對執行緒登錄檔的訊號安全載入的支援也已經融入到這個體系中。當 pthread_join 發生時由核心根據執行緒ID來完成 Futex(fast user space mutex)。(要了解futex的更多資訊,請參閱參考資料).

  POSIX訊號處理在核心空間中完成。一個訊號會傳遞給程式中一個可用的執行緒;銷燬訊號會終止整個程式。停止和繼續訊號也會影響整個程式,這樣就可以實現對多執行緒程式的工作控制。

  引入了退出系統呼叫的一個變種,叫做 exit_group(),這個系統呼叫終止整個程式和它的執行緒。此外,退出處理透過引入O(1)演算法得到了改進,從而可以在兩秒內終止一個具有成千上萬個執行緒的程式(而在2.4核心中完成同樣的事情需要15分鐘)。

  修改了 proc 檔案系統,不再報告所有的執行緒而只是報告原始的執行緒。這樣就避免了 /proc 報告速度的下降。核心保證原始的執行緒在所有其他執行緒終止之前不會終止。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-940300/,如需轉載,請註明出處,否則將追究法律責任。

相關文章