Linux 2.6內核新變化
發表于:2007-07-04來源:作者:點擊數:
標簽:
Linux 內核的 開發 已經經歷了一個漫長的過程,最初是 Linus Torvalds于1991年發布的原始的0.1版本,這個版本中包括一個基本的調度器、IPC(進程間通信)和內存管理算法。而現在它已經是一個以往操作系統的實用的替代品,在市場上表現出了強大的競爭力。越來
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 來分布時間片,并且取消了全局同步和重算循環。
調度器使用了兩個優先級數組,即活動數組和過期數組,可以通過指針來訪問它們?;顒訑到M中包含
了所有映射到某個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中,內核是可搶占的。一個內核任務可以被搶占,為的是讓重要的用戶應用程序可以繼續運行。
這樣做最主要的優勢在于,可以極大地增強系統的用戶交互性,用戶將會覺得鼠標點擊和擊鍵的事件得到
了更快速的響應。
當然,不是所有的內核代碼段都可以被搶占??梢枣i定內核代碼的關鍵部分,不允許搶占。鎖定可以確
保每個 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 報告速度的下降。內核保證原始的線程在
所有其他線程終止之前不會終止。
虛擬內存的變化
從虛擬內存的角度來看,新內核融合了 Rik van Riel 的 r-map (反向映射,reverse mapping)技術,
將顯著改善虛擬內存 在一定程度負載下的性能。
為了理解反向映射技術,讓我們來首先簡單了解 Linux 虛擬內存系統的一些基本原理。
Linux 內核工作于虛擬內存模式:每一個虛擬頁對應一個相應的系統內存的物理頁。虛擬頁和物理頁之間的
地址轉換由硬件的頁表來完成。對于一個特定的虛擬頁,根據一條頁表記錄可以找到對應的物理頁,或者是
頁無法找到的提示(說明存在一個頁錯誤)。但是這種"虛擬到物理"的頁映射不是總是一一對應的:多個虛
擬頁(被不同的進程共享的頁)有可能指向同一個物理頁。在這種情況下,每個共享進程的頁記錄將有指向
對應物理頁的映射。如果有類似這樣的情況,當內核想要釋放特定的物理頁時,事情會變得復雜,因為它必
須遍歷所有的進程頁表記錄來查找指向這個物理頁的引用;它只能在引用數達到0時才能釋放這個物理頁,
因為它沒有別的辦法可以知道是不是還存在實際指向這個頁的引用。這樣當負載較高時會讓虛擬內存變得
非常慢。
反向地址映射補丁通過在結構頁引入一個叫做 pte_chain 的數據結構(物理頁結構)來解決這一問題。
pte_chain 是一個指向頁的 PTE 的簡單鏈接列表,可以返回特定的被引用頁的 PTE 列表。頁釋放一下
子變得非常簡單了。 不過,在這種模式中存在一個指針開銷。系統中的每一個結構頁都必須有一個額外的
用于 pte_chain 的結構。在一個256M內存的系統中,有64K個物理頁,這樣就需要有 64KB * (sizeof(struct pte_chain))
的內存被分配用于 pte_chain 的結構――一個很可觀的數字。
有一些可以解決這個問題的技術,包括從結構頁中刪掉 wait_queue_head_t 域(用于對頁的獨占訪問)。
因為這個等待隊列極少用到,所以在 rmap 補丁中實現了一個更小的隊列,通過哈希隊列來找到正確的等待隊列。
盡管如此,rmap 的性能――尤其是處于高負載的高端系統――相對于2.4內核的虛擬內存系統還是有了顯著的提高。
Linux 2.6的驅動程序移植
2.6內核給驅動程序開發人員帶來了一系列非常有意義的變化。本節重點介紹將驅動程序從2.4內核移植到2.6內核的
一些重要方面。
首先,相對于2.4來說,改進了內核編譯系統,從而獲得更快的編譯速度。加入了改進的圖形化工具:make xconfig
(需要Qt庫)和make gconfig(需要GTK庫)。
當使用make時自動創建 arch-zImage 和模塊
使用 make -jN 可以進行并行的 make
make 默認的不是冗余方式(可以通過設置 KBUILD_VERBOSE=1 或者使用 make V=1來設置為冗余方式)
make subdir/ 將編譯 subdir/ 及其子目錄下的所有文件
make help 將提供 make 目標支持
在任何一個階段都不需要再運行 make dep
內核模塊加載器也在2.5中完全被重新實現,這意味著模塊編譯機制相對于2.4有了很大不同。需要一組新的模
塊工具來完成模塊的加載和缷載 (他們的下載鏈接可以在參考資料中找到),原來的2.4所用的 makefile 在2.6
下不能再用。
新的內核模塊加載器是由 Rusty Russel 開發的。它使用內核編譯機制,產生一個 .ko(內核目標文件,kernel
object)模塊目標文件而不是一個 .o 模塊目標文件。內核編譯系統首先編譯這些模塊,并將其連接成為 vermagic.o。
這一過程在目標模塊創建了一個特定部分,以記錄使用的編譯器版本號,內核版本號,是否使用內核搶占等信息。
現在讓我們來看一個例子,分析一下新的內核編譯系統如何來編譯并加載一個簡單的模塊。這個模塊是一個“hello
world”模塊,代碼和2.4模塊代碼基本類似,只是 module_init 和 module_exit 要換成 init_module 和 cleanup_module
(內核2.4.10模塊已經使用這種機制)。這個模塊命名為 hello.c,Makefile 文件如下:
清單 3. 驅動程序 makefile 文件示例
KERNEL_SRC = /usr/src/linux
SUBDIR = $(KERNEL_SRC)/drivers/char/hello/
all: modules
obj-m := module.o
hello-objs := hello.o
EXTRA_FLAGS += -DDEBUG=1
modules:
$(MAKE) -C $(KERNEL_SRC) SUBDIR=$(SUBDIR) modules
makefile 文件使用內核編譯機制來編譯模塊。編譯好的模塊將被命名為 module.ko,并通過編譯 hello.c 和連接
vermagic 而獲得。KERNEL_SRC 指定內核源文件所在的目錄,SUBDIR 指定放置模塊的目錄。EXTRA_FLAGS
指定了需要給出的編譯期標記。
一旦新模塊(module.ko)被創建,它可以被新的模塊工具加載或缷載。2.4中的原有模塊工具不能用來加載或缷
載2.6的內核模塊。這個新的模塊加載工具會盡量減少在一個設備仍在使用的情況下相應的模塊卻被缷載的沖突發生,
而是在確認這些模塊已經沒有任何設備在使用后再缷載它。產生這種沖突的原因之一是模塊使用計數是由模塊代碼自
己來控制的(通過MOD_DEC/INC_USE_COUNT)。
在2.6中,模塊不再需要對引用計數進行加或減,這些工作將在模塊代碼外部進行。任何要引用模塊的代碼都必須調用
try_module_get(&module),只有在調用成功以后才能訪問那個模塊;如果被調用的模塊已經被缷載,那么這次調用
會失敗。相應的,可以通過使用 module_put() 來釋放對模塊的引用。
內存管理的變化
在2.5的開發過程中,加入了內存池,以滿足無間斷地進行內存分配。其思想是預分配一個內存池,并保留到真正需要
的時候。一個內存池由 mempool_create() 調用來創建(應該包含頭文件 linux/mempool.h)。
mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
mempool_free_t *free_fn, void *pool_data);
在這里 min_nr 是需要預分配對象的數目,alloc_fn 和 free_fn 是指向內存池機制提供的標準對象分配和回收例程的
指針。他們的類型是:
typedef void *(mempool_alloc_t)(int gfp_mask, void *pool_data);
typedef void (mempool_free_t)(void *element, void *pool_data);
pool_data 是分配和回收函數用到的指針,gfp_mask 是分配標記。只有當 __GFP_WAIT 標記被指定時,分配函數才會休眠。
在池中分配和回收對象是由以下程序完成的:
void *mempool_alloc(mempool_t *pool, int gfp_mask);
void mempool_free(void *element, mempool_t *pool);
mempool_alloc() 用來分配對象;如果內存池分配器無法提供內存,那么就可以用預分配的池。
系統使用 mempool_destroy() 來回收內存池。
除了為內存分配引入了內存池之外,2.5內核還引入了三個用于常規內存分配的新的GFP標記,它們是:
__GFP_REPEAT -- 告訴頁分配器盡力去分配內存。如果內存分配失敗過多,應該減少這個標記的使用。
__GFP_NOFAIL -- 不能出現內存分配失敗。這樣,由于調用者被轉入休眠狀態,可能需要一段比較長的時間才能完成分配,調用者的需求才能得到滿足。
__GFP_NORETRY -- 保證分配失敗后不再重試,而向調用者報告失敗狀態。
除了內存分配的變化以外,remap_page_range()調用——用來映射頁到用戶空間——也經過了少量修改。相對于2.4來說,現在它多了一個參數。虛擬內存區域(VMA)指針要作為第一個參數,然后是四個常用的參數(start,end,size 和 protection 標記)。
工作隊列接口
工作隊列接口是在2.5的開發過程中引入的,用于取代任務隊列接口(用于調度內核任務)。每個工作隊列有一個專門的線程,所有來自運行隊列的任務在進程的上下文中運行(這樣它們可以休眠)。驅動程序可以創建并使用它們自己的工作隊列,或者使用內核的一個工作隊列。工作隊列用以下方式創建:
struct workqueue_struct *create_workqueue(const char *name);
在這里 name 是工作隊列的名字。
工作隊列任務可以在編譯時或者運行時創建。任務需要封裝為一個叫做 work_struct 的結構體。在編譯期初始化一個工作隊列任務時要用到:
DECLARE_WORK(name, void (*function)(void *), void *data);
在這里 name 是 work_struct 的名字,function 是當任務被調度時調用的函數,data 是指向那個函數的指針。
在運行期初始化一個工作隊列時要用到:
INIT_WORK(struct work_struct *work, void (*function)(void *), void *data);
用下面的函數調用來把一個作業(一個類型為work_struct 結構的工作隊列作業/任務)加入到工作隊列中:
int queue_work(struct workqueue_struct *queue, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue, struct work_struct
*work, unsigned long delay);
在queue_delay_work()中指定 delay,是為了保證至少在經過一段給定的最小延遲時間以后,工作隊列中的任務才可以真正執行。
工作隊列中的任務由相關的工作線程執行,可能是在一個無法預期的時間(取決于負載,中斷等等),或者是在一段延遲以后。任何一個在工作隊列中等待了無限長的時間也沒有運行的任務可以用下面的方法取消:
int cancel_delayed_work(struct work_struct *work);
如果當一個取消操作的調用返回時,任務正在執行中,那么這個任務將繼續執行下去,但不會再加入到隊列中。清空工作隊列中的所有任務使用:
void flush_workqueue(struct workqueue_struct *queue);
銷毀工作隊列使用:
void destroy_workqueue(struct workqueue_struct *queue);
不是所有的驅動程序都必須有自己的工作隊列。驅動程序可以使用內核提供的缺省工作隊列。由于這個工作隊列由很多驅動程序共享,任務可能會需要比較長一段時間才能開始執行。為了解決這一問題,工作函數中的延遲應該保持最小或者干脆不要。
需要特別注意的是缺省隊列對所有驅動程序來說都是可用的,但是只有經過GP許可的驅動程序可以用自定義的工作隊列:
int schedule_work(struct work_struct *work); -- 向工作隊列中添加一個任務
int schedule_delayed_work(struct work_struct *work, unsigned long delay); -- 向工作隊列中添加一個任務并延遲執行
當模塊被缷載時應該去調用一個 flash_scheduled_work() 函數,這個函數會使等待隊列中所有的任務都被執行。
中斷例程的變化
2.5的中斷處理程序內部已經經歷了許多變化,但是絕大部分對于普通的驅動程序開發者來說沒有影響。不過,還是有一些重要的變化會影響到驅動程序開發者。
現在的中斷處理函數的返回代碼是一個 irqreturn_t 類型。這個由 Linus 引入的變化意味著中斷處理程序告訴通用的 IRQ 層是否真的要中斷。這樣做是為了當中斷請求不斷到來時(原因是驅動程序偶然激活了一個中斷位或者硬件壞掉了),捕獲假中斷(尤其是在共享的PCI線上),而任何驅動程序對此都是無能為力的。在2.6中,驅動程序如果要從一個設備上發出一個中斷需要返回 IRQ_HANDLED,如果不是的話返回 IRQ_NONE。這樣可以幫助內核的 IRQ 層清楚地識別出哪個驅動程序正在處理那個特定的中斷。如果一個中斷請求不斷到來而且沒有注冊那個設備的處理程序(例如,所有的驅動程序都返回 IRQ_NONE),內核就會忽略來自那個設備的中斷。缺省情況下,驅動程序 IRQ 例程應該返回 IRQ_HANDLED,當驅動程序正在處理那個中斷時卻返回了 IRQ_NONE,說明存在 bug。新的中斷處理程序可能是類似于這樣:
清單 4. 2.6的中斷處理程序偽代碼
irqreturn_t irq_handler(...) {
..
if (!(my_interrupt)
return IRQ_NONE; // not our interrupt
...
return IRQ_HANDLED; // return by default
}
注意,cli(),sti(),save_flags()和 restor_flags() 是不贊成使用的方法。取而代之的是 local_save_flags() 和 local_irq_disable(),用來禁止所有的本地中斷(本處理器內的)。禁止所有處理器的中斷是不可能的。
統一的設備模型
2.5開發過程中另一個最值得關注的變化是創建了一個統一的設備模型。這個設備模型通過維持大量的數據結構囊括了幾乎所有的設備結構和系統。這樣做的好處是,可以改進設備的電源管理和簡化設備相關的任務管理,包括對以下信息的追蹤:
系統中存在的設備,其所連接的總線
特定情形下設備的電源狀態
系統清楚設備的驅動程序,并清楚哪些設備受其控制
系統的總線結構:哪個設備連接在哪個總線上,以及哪些總線互連(例如,USB和PCI總線的互連)
設備在系統中的類別描述(類別包括磁盤,分區等等)
在2.5內核中,與設備驅動程序相關的其他發展包括:
不再使用 malloc.h。所有包含 (用于內存分配)的代碼現在要替換為 。
用于 x86 體系結構的 HZ 值增加到1000。引入了一個叫做 jiffies_64 的瞬間計算器,以避免由于 HZ 值的變化而引起瞬間變量的迅速溢出。
引入了一個叫做 ndelay() 的新的延遲函數,允許納秒級的等待。
引入了一個叫做 seqlock() 的新類型的鎖,用于鎖定小段的經常被訪問的數據(不是指針)。
由于2.6內核可以搶占,應該在驅動程序中使用 preempt_disable() 和 preempt_enable(),從而保護代碼段不被搶占(禁止 IRQ 同時也就隱式地禁止了搶占)。
在2.5中加入了異步 I/O。這意味著用戶進程可以同時進行多個 I/O 操作,而不用等待它們完成。在字符驅動程序中引入了異步 API。
塊層在2.5的開發過程中經歷了大幅度的變化。這意味著原來用于2.4的塊設備需要進行重新設計。
在2.5中引入了sys文件系統,它給出了系統的設備模型的用戶空間描述。它掛載在 /sys 目錄下。
結束語
由于相對于2.4來說 Linux2.6發生了太多的變化,所以在 Linux 內核界有一種說法是新的發布版本應該命名為3.0。Linus 將最終決定如何命名,官方可能將于2003年11月發布官方版本。不管最終采用哪個版本號,相對于2.4來說,新的內核發布版本在多種平臺和體系結構上性能將更快,可擴展性更強,更加穩定。
Linus 已經邀請世界各地的測試人員來查找 bug 和報告問題,并要求發行者提供2.6版本的下載。
原文轉自:http://www.kjueaiud.com