linux内核技术文章
生活随笔
收集整理的這篇文章主要介紹了
linux内核技术文章
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Linux 引導過程內(nèi)幕
從主引導記錄到第一個用戶空間應(yīng)用程序的指導引導 Linux? 系統(tǒng)的過程包括很多階段。不管您是引導一個標準的 x86 桌面系統(tǒng),還是引導一臺嵌入式
的 PowerPC? 機器,很多流程都驚人地相似。本文將探索 Linux 的引導過程,從最初的引導到啟動第一
個用戶空間應(yīng)用程序。在本文介紹的過程中,您將學習到各種與引導有關(guān)的主題,例如引導加載程序、
內(nèi)核解壓、初始 RAM 磁盤以及 Linux 引導的其他一些元素。
早期時,啟動一臺計算機意味著要給計算機喂一條包含引導程序的紙帶,或者手工使用前端面板地址/數(shù)
據(jù)/控制開關(guān)來加載引導程序。盡管目前的計算機已經(jīng)裝備了很多工具來簡化引導過程,但是這一切并沒
有對整個過程進行必要的簡化。
各個步驟到底發(fā)生了什么。在整個過程中,參考一下內(nèi)核源代碼可以幫助我們更好地了解內(nèi)核源代碼樹
,并在以后對其進行深入分析。
概述
圖 1 是我們在 20,000 英尺的高度看到的視圖。
圖 1. Linux 引導過程在 20,000 英尺處的視圖
Linux 引導過程在 20,000 英尺處的視圖
中,這個位置在基本輸入/輸出系統(tǒng)(BIOS)中,它保存在主板上的閃存中。嵌入式系統(tǒng)中的中央處理單
元(CPU)會調(diào)用這個重置向量來啟動一個位于閃存/ROM 中的已知地址處的程序。在這兩種情況下,結(jié)
果都是相同的。因為 PC 提供了很多靈活性,BIOS 必須確定要使用哪個設(shè)備來引導系統(tǒng)。稍后我們將詳
細介紹這個過程。
當找到一個引導設(shè)備之后,第一階段的引導加載程序就被裝入 RAM 并執(zhí)行。這個引導加載程序在大小上
小于 512 字節(jié)(一個扇區(qū)),其作用是加載第二階段的引導加載程序。當?shù)诙A段的引導加載程序被裝入 RAM 并執(zhí)行時,通常會顯示一個動畫屏幕,并將 Linux 和一個可選
的初始 RAM 磁盤(臨時根文件系統(tǒng))加載到內(nèi)存中。在加載映像時,第二階段的引導加載程序就會將控
制權(quán)交給內(nèi)核映像,然后內(nèi)核就可以進行解壓和初始化了。在這個階段中,第二階段的引導加載程序會
檢測系統(tǒng)硬件、枚舉系統(tǒng)鏈接的硬件設(shè)備、掛載根設(shè)備,然后加載必要的內(nèi)核模塊。完成這些操作之后
啟動第一個用戶空間程序(init),并執(zhí)行高級系統(tǒng)初始化工作。
這就是 Linux 引導的整個過程。現(xiàn)在讓我們深入挖掘一下這個過程,并深入研究一下 Linux 引導過程
的一些詳細信息。系統(tǒng)啟動
系統(tǒng)啟動階段依賴于引導 Linux 系統(tǒng)上的硬件。在嵌入式平臺中,當系統(tǒng)加電或重置時,會使用一個啟
動環(huán)境。這方面的例子包括 U-Boot、RedBoot 和 Lucent 的 MicroMonitor。嵌入式平臺通常都是與引
導監(jiān)視器搭配銷售的。這些程序位于目標硬件上的閃存中的某一段特殊區(qū)域,它們提供了將 Linux 內(nèi)核
映像下載到閃存并繼續(xù)執(zhí)行的方法。除了可以存儲并引導 Linux 映像之外,這些引導監(jiān)視器還執(zhí)行一定
級別的系統(tǒng)測試和硬件初始化過程。在嵌入式平臺中,這些引導監(jiān)視器通常會涉及第一階段和第二階段
的引導加載程序。
提取 MBR 的信息
要查看 MBR 的內(nèi)容,請使用下面的命令:# dd if=/dev/hda of=mbr.bin bs=512 count=1 # od -xa mbr.bin
這個 dd 命令需要以 root 用戶的身份運行,它從 /dev/hda(第一個 IDE 盤) 上讀取前 512 個字節(jié)
的內(nèi)容,并將其寫入 mbr.bin 文件中。od 命令會以十六進制和 ASCII 碼格式打印這個二進制文件的內(nèi)
容。
在 PC 中,引導 Linux 是從 BIOS 中的地址 0xFFFF0 處開始的。BIOS 的第一個步驟是加電自檢(POST
)。POST 的工作是對硬件進行檢測。BIOS 的第二個步驟是進行本地設(shè)備的枚舉和初始化。給定 BIOS 功能的不同用法之后,BIOS 由兩部分組成:POST 代碼和運行時服務(wù)。當 POST 完成之后,
它被從內(nèi)存中清理了出來,但是 BIOS 運行時服務(wù)依然保留在內(nèi)存中,目標操作系統(tǒng)可以使用這些服務(wù)
。
要引導一個操作系統(tǒng),BIOS 運行時會按照 CMOS 的設(shè)置定義的順序來搜索處于活動狀態(tài)并且可以引導的
設(shè)備。引導設(shè)備可以是軟盤、CD-ROM、硬盤上的某個分區(qū)、網(wǎng)絡(luò)上的某個設(shè)備,甚至是 USB 閃存。通常,Linux 都是從硬盤上引導的,其中主引導記錄(MBR)中包含主引導加載程序。MBR 是一個 512?
字節(jié)大小的扇區(qū),位于磁盤上的第一個扇區(qū)中(0 道 0 柱面 1 扇區(qū))。當 MBR 被加載到 RAM 中之后
,BIOS 就會將控制權(quán)交給 MBR。
第一階段引導加載程序
MBR 中的主引導加載程序是一個 512 字節(jié)大小的映像,其中包含程序代碼和一個小分區(qū)表(參見圖 2)
。前 446 個字節(jié)是主引導加載程序,其中包含可執(zhí)行代碼和錯誤消息文本。接下來的 64 個字節(jié)是分區(qū)
表,其中包含 4 個分區(qū)的記錄(每個記錄的大小是 16 個字節(jié))。MBR 以兩個特殊數(shù)字的字節(jié)(0xAA55
)結(jié)束。這個數(shù)字會用來進行 MBR 的有效性檢查。
圖 2. MBR 剖析
MBR 剖析
主引導加載程序的工作是查找并加載次引導加載程序(第二階段)。它是通過在分區(qū)表中查找一個活動分區(qū)來實現(xiàn)這種功能的。當找到一個活動分區(qū)時,它會掃描分區(qū)表中的其他分區(qū),以確保它們都不是活
動的。當這個過程驗證完成之后,就將活動分區(qū)的引導記錄從這個設(shè)備中讀入 RAM 中并執(zhí)行它。
第二階段引導加載程序
次引導加載程序(第二階段引導加載程序)可以更形象地稱為內(nèi)核加載程序。這個階段的任務(wù)是加載?
Linux 內(nèi)核和可選的初始 RAM 磁盤。
GRUB 階段引導加載程序
/boot/grub 目錄中包含了 stage1、stage1.5 和 stage2 引導加載程序,以及很多其他加載程序(例如,CR-ROM 使用的是 iso9660_stage_1_5)。
在 x86 PC 環(huán)境中,第一階段和第二階段的引導加載程序一起稱為 Linux Loader(LILO)或 GRand?
Unified Bootloader(GRUB)。由于 LILO 有一些缺點,而 GRUB 克服了這些缺點,因此下面讓我們就
來看一下 GRUB。(有關(guān) GRUB、LILO 和相關(guān)主題的更多內(nèi)容,請參閱本文后面的 參考資料 部分的內(nèi)容
。)
關(guān)于 GRUB,很好的一件事情是它包含了有關(guān) Linux 文件系統(tǒng)的知識。GRUB 不像 LILO 一樣使用裸扇區(qū)
,而是可以從 ext2 或 ext3 文件系統(tǒng)中加載 Linux 內(nèi)核。它是通過將兩階段的引導加載程序轉(zhuǎn)換成三
階段的引導加載程序來實現(xiàn)這項功能的。階段 1 (MBR)引導了一個階段 1.5 的引導加載程序,它可以
理解包含 Linux 內(nèi)核映像的特殊文件系統(tǒng)。這方面的例子包括 reiserfs_stage1_5(要從 Reiser 日志
文件系統(tǒng)上進行加載)或 e2fs_stage1_5(要從 ext2 或 ext3 文件系統(tǒng)上進行加載)。當階段 1.5 的
引導加載程序被加載并運行時,階段 2 的引導加載程序就可以進行加載了。
當階段 2 加載之后,GRUB 就可以在請求時顯示可用內(nèi)核列表(在 /etc/grub.conf 中進行定義,同時
還有幾個軟符號鏈接 /etc/grub/menu.lst 和 /etc/grub.conf)。我們可以選擇內(nèi)核甚至修改附加內(nèi)核
參數(shù)。另外,我們也可以使用一個命令行的 shell 對引導過程進行高級手工控制。
將第二階段的引導加載程序加載到內(nèi)存中之后,就可以對文件系統(tǒng)進行查詢了,并將默認的內(nèi)核映像和?
initrd 映像加載到內(nèi)存中。當這些映像文件準備好之后,階段 2 的引導加載程序就可以調(diào)用內(nèi)核映像
了。
內(nèi)核
GRUB 中的手工引導
在 GRUB 命令行中,我們可以使用 initrd 映像引導一個特定的內(nèi)核,方法如下:
grub> kernel /bzImage-2.6.14.2
[Linux-bzImage, setup=0x1400, size=0x29672e]
grub> initrd /initrd-2.6.14.2.img
[Linux-initrd @ 0x5f13000, 0xcc199 bytes]
grub> boot
Uncompressing Linux... Ok, booting the kernel.
如果您不知道要引導的內(nèi)核的名稱,只需使用斜線(/)然后按下 Tab 鍵即可。GRUB 會顯示內(nèi)核和?
initrd 映像列表。
當內(nèi)核映像被加載到內(nèi)存中,并且階段 2 的引導加載程序釋放控制權(quán)之后,內(nèi)核階段就開始了。內(nèi)核映
像并不是一個可執(zhí)行的內(nèi)核,而是一個壓縮過的內(nèi)核映像。通常它是一個 zImage(壓縮映像,小于?
512KB)或一個 bzImage(較大的壓縮映像,大于 512KB),它是提前使用 zlib 進行壓縮過的。在這個
內(nèi)核映像前面是一個例程,它實現(xiàn)少量硬件設(shè)置,并對內(nèi)核映像中包含的內(nèi)核進行解壓,然后將其放入
高端內(nèi)存中,如果有初始 RAM 磁盤映像,就會將它移動到內(nèi)存中,并標明以后使用。然后該例程會調(diào)用
內(nèi)核,并開始啟動內(nèi)核引導的過程。
當 bzImage(用于 i386 映像)被調(diào)用時,我們從 ./arch/i386/boot/head.S 的 start 匯編例程開始
執(zhí)行(主要流程圖請參看圖 3)。這個例程會執(zhí)行一些基本的硬件設(shè)置,并調(diào)用?
./arch/i386/boot/compressed/head.S 中的 startup_32 例程。此例程會設(shè)置一個基本的環(huán)境(堆棧等
),并清除 Block Started by Symbol(BSS)。然后調(diào)用一個叫做 decompress_kernel 的 C 函數(shù)(在?
./arch/i386/boot/compressed/misc.c 中)來解壓內(nèi)核。當內(nèi)核被解壓到內(nèi)存中之后,就可以調(diào)用它了
。這是另外一個 startup_32 函數(shù),但是這個函數(shù)在 ./arch/i386/kernel/head.S 中。
在這個新的 startup_32 函數(shù)(也稱為清除程序或進程 0)中,會對頁表進行初始化,并啟用內(nèi)存分頁
功能。然后會為任何可選的浮點單元(FPU)檢測 CPU 的類型,并將其存儲起來供以后使用。然后調(diào)用?
start_kernel 函數(shù)(在 init/main.c 中),它會將您帶入與體系結(jié)構(gòu)無關(guān)的 Linux 內(nèi)核部分。實際上
,這就是 Linux 內(nèi)核的 main 函數(shù)。
圖 3. Linux 內(nèi)核 i386 引導的主要函數(shù)流程
Linux 內(nèi)核 i386 引導的主要函數(shù)流程
通過調(diào)用 start_kernel,會調(diào)用一系列初始化函數(shù)來設(shè)置中斷,執(zhí)行進一步的內(nèi)存配置,并加載初始?RAM 磁盤。最后,要調(diào)用 kernel_thread(在 arch/i386/kernel/process.c 中)來啟動 init 函數(shù),
這是第一個用戶空間進程(user-space process)。最后,啟動空任務(wù),現(xiàn)在調(diào)度器就可以接管控制權(quán)
了(在調(diào)用 cpu_idle 之后)。通過啟用中斷,搶占式的調(diào)度器就可以周期性地接管控制權(quán),從而提供
多任務(wù)處理能力。
在內(nèi)核引導過程中,初始 RAM 磁盤(initrd)是由階段 2 引導加載程序加載到內(nèi)存中的,它會被復制
到 RAM 中并掛載到系統(tǒng)上。這個 initrd 會作為 RAM 中的臨時根文件系統(tǒng)使用,并允許內(nèi)核在沒有掛
載任何物理磁盤的情況下完整地實現(xiàn)引導。由于與外圍設(shè)備進行交互所需要的模塊可能是 initrd 的一
部分,因此內(nèi)核可以非常小,但是仍然需要支持大量可能的硬件配置。在內(nèi)核引導之后,就可以正式裝
備根文件系統(tǒng)了(通過 pivot_root):此時會將 initrd 根文件系統(tǒng)卸載掉,并掛載真正的根文件系統(tǒng)
。
decompress_kernel 輸出
函數(shù) decompress_kernel 就是顯示我們通常看到的解壓消息的地方:
Uncompressing Linux... Ok, booting the kernel.
initrd 函數(shù)讓我們可以創(chuàng)建一個小型的 Linux 內(nèi)核,其中包括作為可加載模塊編譯的驅(qū)動程序。這些
可加載的模塊為內(nèi)核提供了訪問磁盤和磁盤上的文件系統(tǒng)的方法,并為其他硬件提供了驅(qū)動程序。由于
根文件系統(tǒng)是磁盤上的一個文件系統(tǒng),因此 initrd 函數(shù)會提供一種啟動方法來獲得對磁盤的訪問,并
掛載真正的根文件系統(tǒng)。在一個沒有硬盤的嵌入式環(huán)境中,initrd 可以是最終的根文件系統(tǒng),或者也可
以通過網(wǎng)絡(luò)文件系統(tǒng)(NFS)來掛載最終的根文件系統(tǒng)。
Init
當內(nèi)核被引導并進行初始化之后,內(nèi)核就可以啟動自己的第一個用戶空間應(yīng)用程序了。這是第一個調(diào)用
的使用標準 C 庫編譯的程序。在此之前,還沒有執(zhí)行任何標準的 C 應(yīng)用程序。
在桌面 Linux 系統(tǒng)上,第一個啟動的程序通常是 /sbin/init。但是這不是一定的。很少有嵌入式系統(tǒng)
會需要使用 init 所提供的豐富初始化功能(這是通過 /etc/inittab 進行配置的)。在很多情況下,
我們可以調(diào)用一個簡單的 shell 腳本來啟動必需的嵌入式應(yīng)用程序。
結(jié)束語
與 Linux 本身非常類似,Linux 的引導過程也非常靈活,可以支持眾多的處理器和硬件平臺。最初,加
載引導加載程序提供了一種簡單的方法,不用任何花架子就可以引導 Linux。LILO 引導加載程序?qū)σ龑?
能力進行了擴充,但是它卻缺少文件系統(tǒng)的感知能力。最新一代的引導加載程序,例如 GRUB,允許?
Linux 從一些文件系統(tǒng)(從 Minix 到 Reise)上進行引導。
========
Linux slab 分配器剖析
了解 Linux 內(nèi)存管理的方式良好的操作系統(tǒng)性能部分依賴于操作系統(tǒng)有效管理資源的能力。在過去,堆內(nèi)存管理器是實際的規(guī)范,
但是其性能會受到內(nèi)存碎片和內(nèi)存回收需求的影響。現(xiàn)在,Linux? 內(nèi)核使用了源自于 Solaris 的一種
方法,但是這種方法在嵌入式系統(tǒng)中已經(jīng)使用了很長時間了,它是將內(nèi)存作為對象按照大小進行分配。
本文將探索 slab 分配器背后所采用的思想,并介紹這種方法提供的接口和用法。
動態(tài)內(nèi)存管理
內(nèi)存管理的目標是提供一種方法,為實現(xiàn)各種目的而在各個用戶之間實現(xiàn)內(nèi)存共享。內(nèi)存管理方法應(yīng)該
實現(xiàn)以下兩個功能:
最小化管理內(nèi)存所需的時間
最大化用于一般應(yīng)用的可用內(nèi)存(最小化管理開銷)
內(nèi)存管理實際上是一種關(guān)于權(quán)衡的零和游戲。您可以開發(fā)一種使用少量內(nèi)存進行管理的算法,但是要花
費更多時間來管理可用內(nèi)存。也可以開發(fā)一個算法來有效地管理內(nèi)存,但卻要使用更多的內(nèi)存。最終,
特定應(yīng)用程序的需求將促使對這種權(quán)衡作出選擇。
每個內(nèi)存管理器都使用了一種基于堆的分配策略。在這種方法中,大塊內(nèi)存(稱為 堆)用來為用戶定義
的目的提供內(nèi)存。當用戶需要一塊內(nèi)存時,就請求給自己分配一定大小的內(nèi)存。堆管理器會查看可用內(nèi)
存的情況(使用特定算法)并返回一塊內(nèi)存。搜索過程中使用的一些算法有 first-fit(在堆中搜索到
的第一個滿足請求的內(nèi)存塊 )和 best-fit(使用堆中滿足請求的最合適的內(nèi)存塊)。當用戶使用完內(nèi)
存后,就將內(nèi)存返回給堆。
這種基于堆的分配策略的根本問題是碎片(fragmentation)。當內(nèi)存塊被分配后,它們會以不同的順序
在不同的時間返回。這樣會在堆中留下一些洞,需要花一些時間才能有效地管理空閑內(nèi)存。這種算法通
常具有較高的內(nèi)存使用效率(分配需要的內(nèi)存),但是卻需要花費更多時間來對堆進行管理。
另外一種方法稱為 buddy memory allocation,是一種更快的內(nèi)存分配技術(shù),它將內(nèi)存劃分為 2 的冪次
方個分區(qū),并使用 best-fit 方法來分配內(nèi)存請求。當用戶釋放內(nèi)存時,就會檢查 buddy 塊,查看其相
鄰的內(nèi)存塊是否也已經(jīng)被釋放。如果是的話,將合并內(nèi)存塊以最小化內(nèi)存碎片。這個算法的時間效率更
高,但是由于使用 best-fit 方法的緣故,會產(chǎn)生內(nèi)存浪費。
本文將著重介紹 Linux 內(nèi)核的內(nèi)存管理,尤其是 slab 分配提供的機制。
slab 緩存
Linux 所使用的 slab 分配器的基礎(chǔ)是 Jeff Bonwick 為 SunOS 操作系統(tǒng)首次引入的一種算法。Jeff?
的分配器是圍繞對象緩存進行的。在內(nèi)核中,會為有限的對象集(例如文件描述符和其他常見結(jié)構(gòu))分
配大量內(nèi)存。Jeff 發(fā)現(xiàn)對內(nèi)核中普通對象進行初始化所需的時間超過了對其進行分配和釋放所需的時間
。因此他的結(jié)論是不應(yīng)該將內(nèi)存釋放回一個全局的內(nèi)存池,而是將內(nèi)存保持為針對特定目而初始化的狀
態(tài)。例如,如果內(nèi)存被分配給了一個互斥鎖,那么只需在為互斥鎖首次分配內(nèi)存時執(zhí)行一次互斥鎖初始
化函數(shù)(mutex_init)即可。后續(xù)的內(nèi)存分配不需要執(zhí)行這個初始化函數(shù),因為從上次釋放和調(diào)用析構(gòu)
之后,它已經(jīng)處于所需的狀態(tài)中了。
Linux slab 分配器使用了這種思想和其他一些思想來構(gòu)建一個在空間和時間上都具有高效性的內(nèi)存分配
器。
圖 1 給出了 slab 結(jié)構(gòu)的高層組織結(jié)構(gòu)。在最高層是 cache_chain,這是一個 slab 緩存的鏈接列表。
這對于 best-fit 算法非常有用,可以用來查找最適合所需要的分配大小的緩存(遍歷列表)。
cache_chain 的每個元素都是一個 kmem_cache 結(jié)構(gòu)的引用(稱為一個 cache)。它定義了一個要管理
的給定大小的對象池。
圖 1. slab 分配器的主要結(jié)構(gòu)
圖 1. slab 分配器的主要結(jié)構(gòu)
每個緩存都包含了一個 slabs 列表,這是一段連續(xù)的內(nèi)存塊(通常都是頁面)。存在 3 種 slab:
slabs_full
完全分配的 slab
slabs_partial
部分分配的 slab
slabs_empty
空 slab,或者沒有對象被分配
注意 slabs_empty 列表中的 slab 是進行回收(reaping)的主要備選對象。正是通過此過程,slab 所
使用的內(nèi)存被返回給操作系統(tǒng)供其他用戶使用。
slab 列表中的每個 slab 都是一個連續(xù)的內(nèi)存塊(一個或多個連續(xù)頁),它們被劃分成一個個對象。這
些對象是從特定緩存中進行分配和釋放的基本元素。注意 slab 是 slab 分配器進行操作的最小分配單
位,因此如果需要對 slab 進行擴展,這也就是所擴展的最小值。通常來說,每個 slab 被分配為多個
對象。
由于對象是從 slab 中進行分配和釋放的,因此單個 slab 可以在 slab 列表之間進行移動。例如,當
一個 slab 中的所有對象都被使用完時,就從 slabs_partial 列表中移動到 slabs_full 列表中。當一
個 slab 完全被分配并且有對象被釋放后,就從 slabs_full 列表中移動到 slabs_partial 列表中。當
所有對象都被釋放之后,就從 slabs_partial 列表移動到 slabs_empty 列表中。
slab 背后的動機
與傳統(tǒng)的內(nèi)存管理模式相比, slab 緩存分配器提供了很多優(yōu)點。首先,內(nèi)核通常依賴于對小對象的分
配,它們會在系統(tǒng)生命周期內(nèi)進行無數(shù)次分配。slab 緩存分配器通過對類似大小的對象進行緩存而提供
這種功能,從而避免了常見的碎片問題。slab 分配器還支持通用對象的初始化,從而避免了為同一目而
對一個對象重復進行初始化。最后,slab 分配器還可以支持硬件緩存對齊和著色,這允許不同緩存中的
對象占用相同的緩存行,從而提高緩存的利用率并獲得更好的性能。
回頁首
API 函數(shù)
現(xiàn)在來看一下能夠創(chuàng)建新 slab 緩存、向緩存中增加內(nèi)存、銷毀緩存的應(yīng)用程序接口(API)以及 slab?
中對對象進行分配和釋放操作的函數(shù)。
第一個步驟是創(chuàng)建 slab 緩存結(jié)構(gòu),您可以將其靜態(tài)創(chuàng)建為:
struct struct kmem_cache *my_cachep;
然后其他 slab 緩存函數(shù)將使用該引用進行創(chuàng)建、刪除、分配等操作。kmem_cache 結(jié)構(gòu)包含了每個中央
處理器單元(CPU)的數(shù)據(jù)、一組可調(diào)整的(可以通過 proc 文件系統(tǒng)訪問)參數(shù)、統(tǒng)計信息和管理?
slab 緩存所必須的元素。
kmem_cache_create
內(nèi)核函數(shù) kmem_cache_create 用來創(chuàng)建一個新緩存。這通常是在內(nèi)核初始化時執(zhí)行的,或者在首次加載
內(nèi)核模塊時執(zhí)行。其原型定義如下:
struct kmem_cache *
kmem_cache_create( const char *name, size_t size, size_t align,
? ? ? ? ? ? ? ? ? ? ? ?unsigned long flags;
? ? ? ? ? ? ? ? ? ? ? ?void (*ctor)(void*, struct kmem_cache *, unsigned long),
? ? ? ? ? ? ? ? ? ? ? ?void (*dtor)(void*, struct kmem_cache *, unsigned long));
name 參數(shù)定義了緩存名稱,proc 文件系統(tǒng)(在 /proc/slabinfo 中)使用它標識這個緩存。 size 參
數(shù)指定了為這個緩存創(chuàng)建的對象的大小, align 參數(shù)定義了每個對象必需的對齊。 flags 參數(shù)指定了
為緩存啟用的選項。這些標志如表 1 所示。
表 1. kmem_cache_create 的部分選項(在 flags 參數(shù)中指定)
選項 說明
SLAB_RED_ZONE 在對象頭、尾插入標志,用來支持對緩沖區(qū)溢出的檢查。
SLAB_POISON 使用一種己知模式填充 slab,允許對緩存中的對象進行監(jiān)視(對象屬對象所有,不過
可以在外部進行修改)。
SLAB_HWCACHE_ALIGN 指定緩存對象必須與硬件緩存行對齊。
ctor 和 dtor 參數(shù)定義了一個可選的對象構(gòu)造器和析構(gòu)器。構(gòu)造器和析構(gòu)器是用戶提供的回調(diào)函數(shù)。當
從緩存中分配新對象時,可以通過構(gòu)造器進行初始化。
在創(chuàng)建緩存之后, kmem_cache_create 函數(shù)會返回對它的引用。注意這個函數(shù)并沒有向緩存分配任何內(nèi)
存。相反,在試圖從緩存(最初為空)分配對象時,refill 操作將內(nèi)存分配給它。當所有對象都被使用
掉時,也可以通過相同的操作向緩存添加內(nèi)存。
kmem_cache_destroy
內(nèi)核函數(shù) kmem_cache_destroy 用來銷毀緩存。這個調(diào)用是由內(nèi)核模塊在被卸載時執(zhí)行的。在調(diào)用這個
函數(shù)時,緩存必須為空。
void kmem_cache_destroy( struct kmem_cache *cachep );
kmem_cache_alloc
要從一個命名的緩存中分配一個對象,可以使用 kmem_cache_alloc 函數(shù)。調(diào)用者提供了從中分配對象
的緩存以及一組標志:
void kmem_cache_alloc( struct kmem_cache *cachep, gfp_t flags );
這個函數(shù)從緩存中返回一個對象。注意如果緩存目前為空,那么這個函數(shù)就會調(diào)用 cache_alloc_refill?
向緩存中增加內(nèi)存。 kmem_cache_alloc 的 flags 選項與 kmalloc 的 flags 選項相同。表 2 給出了
標志選項的部分列表。
表 2. kmem_cache_alloc 和 kmalloc 內(nèi)核函數(shù)的標志選項
標志 說明
GFP_USER 為用戶分配內(nèi)存(這個調(diào)用可能會睡眠)。
GFP_KERNEL 從內(nèi)核 RAM 中分配內(nèi)存(這個調(diào)用可能會睡眠)。
GFP_ATOMIC 使該調(diào)用強制處于非睡眠狀態(tài)(對中斷處理程序非常有用)。
GFP_HIGHUSER 從高端內(nèi)存中分配內(nèi)存。
kmem_cache_zalloc
內(nèi)核函數(shù) kmem_cache_zalloc 與 kmem_cache_alloc 類似,只不過它對對象執(zhí)行 memset 操作,用來在
將對象返回調(diào)用者之前對其進行清除操作。
kmem_cache_free
要將一個對象釋放回 slab,可以使用 kmem_cache_free。調(diào)用者提供了緩存引用和要釋放的對象。
void kmem_cache_free( struct kmem_cache *cachep, void *objp );
kmalloc 和 kfree
內(nèi)核中最常用的內(nèi)存管理函數(shù)是 kmalloc 和 kfree 函數(shù)。這兩個函數(shù)的原型如下:
void *kmalloc( size_t size, int flags );
void kfree( const void *objp );
注意在 kmalloc 中,惟一兩個參數(shù)是要分配的對象的大小和一組標志(請參看 表 2 中的部分列表)。
但是 kmalloc 和 kfree 使用了類似于前面定義的函數(shù)的 slab 緩存。kmalloc 沒有為要從中分配對象
的某個 slab 緩存命名,而是循環(huán)遍歷可用緩存來查找可以滿足大小限制的緩存。找到之后,就(使用?
__kmem_cache_alloc)分配一個對象。要使用 kfree 釋放對象,從中分配對象的緩存可以通過調(diào)用?
virt_to_cache 確定。這個函數(shù)會返回一個緩存引用,然后在 __cache_free 調(diào)用中使用該引用釋放對
象。
其他函數(shù)
slab 緩存 API 還提供了其他一些非常有用的函數(shù)。 kmem_cache_size 函數(shù)會返回這個緩存所管理的對
象的大小。您也可以通過調(diào)用 kmem_cache_name 來檢索給定緩存的名稱(在創(chuàng)建緩存時定義)。緩存可
以通過釋放其中的空閑 slab 進行收縮。這可以通過調(diào)用 kmem_cache_shrink 實現(xiàn)。注意這個操作(稱
為回收)是由內(nèi)核定期自動執(zhí)行的(通過 kswapd)。
unsigned int kmem_cache_size( struct kmem_cache *cachep );
const char *kmem_cache_name( struct kmem_cache *cachep );
int kmem_cache_shrink( struct kmem_cache *cachep );
回頁首
slab 緩存的示例用法
下面的代碼片斷展示了創(chuàng)建新 slab 緩存、從緩存中分配和釋放對象然后銷毀緩存的過程。首先,必須
要定義一個 kmem_cache 對象,然后對其進行初始化(請參看清單 1)。這個特定的緩存包含 32 字節(jié)
的對象,并且是硬件緩存對齊的(由標志參數(shù) SLAB_HWCACHE_ALIGN 定義)。
清單 1. 創(chuàng)建新 slab 緩存
static struct kmem_cache *my_cachep;
static void init_my_cache( void )
{
? ?my_cachep = kmem_cache_create(?
? ? ? ? ? ? ? ? ? "my_cache", ? ? ? ? ? ?/* Name */
? ? ? ? ? ? ? ? ? 32, ? ? ? ? ? ? ? ? ? ?/* Object Size */
? ? ? ? ? ? ? ? ? 0, ? ? ? ? ? ? ? ? ? ? /* Alignment */
? ? ? ? ? ? ? ? ? SLAB_HWCACHE_ALIGN, ? ?/* Flags */
? ? ? ? ? ? ? ? ? NULL, NULL ); ? ? ? ? ?/* Constructor/Deconstructor */
? ?return;
}
使用所分配的 slab 緩存,您現(xiàn)在可以從中分配一個對象了。清單 2 給出了一個從緩存中分配和釋放對
象的例子。它還展示了兩個其他函數(shù)的用法。
清單 2. 分配和釋放對象
int slab_test( void )
{
? void *object;
? printk( "Cache name is %s\n", kmem_cache_name( my_cachep ) );
? printk( "Cache object size is %d\n", kmem_cache_size( my_cachep ) );
? object = kmem_cache_alloc( my_cachep, GFP_KERNEL );
? if (object) {
? ? kmem_cache_free( my_cachep, object );
? }
? return 0;
}
最后,清單 3 演示了 slab 緩存的銷毀。調(diào)用者必須確保在執(zhí)行銷毀操作過程中,不要從緩存中分配對
象。
清單 3. 銷毀 slab 緩存
static void remove_my_cache( void )
{
? if (my_cachep) kmem_cache_destroy( my_cachep );
? return;
}
回頁首
slab 的 proc 接口
proc 文件系統(tǒng)提供了一種簡單的方法來監(jiān)視系統(tǒng)中所有活動的 slab 緩存。這個文件稱為?
/proc/slabinfo,它除了提供一些可以從用戶空間訪問的可調(diào)整參數(shù)之外,還提供了有關(guān)所有 slab 緩
存的詳細信息。當前版本的 slabinfo 提供了一個標題,這樣輸出結(jié)果就更具可讀性。對于系統(tǒng)中的每
個 slab 緩存來說,這個文件提供了對象數(shù)量、活動對象數(shù)量以及對象大小的信息(除了每個 slab 的
對象和頁面之外)。另外還提供了一組可調(diào)整的參數(shù)和 slab 數(shù)據(jù)。
要調(diào)優(yōu)特定的 slab 緩存,可以簡單地向 /proc/slabinfo 文件中以字符串的形式回轉(zhuǎn) slab 緩存名稱
和 3 個可調(diào)整的參數(shù)。下面的例子展示了如何增加 limit 和 batchcount 的值,而保留 shared?
factor 不變(格式為 “cache name limit batchcount shared factor”):
# echo "my_cache 128 64 8" > /proc/slabinfo
limit 字段表示每個 CPU 可以緩存的對象的最大數(shù)量。 batchcount 字段是當緩存為空時轉(zhuǎn)換到每個?
CPU 緩存中全局緩存對象的最大數(shù)量。 shared 參數(shù)說明了對稱多處理器(Symmetric MultiProcessing
,SMP)系統(tǒng)的共享行為。
注意您必須具有超級用戶的特權(quán)才能在 proc 文件系統(tǒng)中為 slab 緩存調(diào)優(yōu)參數(shù)。
回頁首
SLOB 分配器
對于小型的嵌入式系統(tǒng)來說,存在一個 slab 模擬層,名為 SLOB。這個 slab 的替代品在小型嵌入式?
Linux 系統(tǒng)中具有優(yōu)勢,但是即使它保存了 512KB 內(nèi)存,依然存在碎片和難于擴展的問題。在禁用?
CONFIG_SLAB 時,內(nèi)核會回到這個 SLOB 分配器中。更多信息請參看 參考資料 一節(jié)。
回頁首
結(jié)束語
slab 緩存分配器的源代碼實際上是 Linux 內(nèi)核中可讀性較好的一部分。除了函數(shù)調(diào)用的間接性之外,
源代碼也非常直觀,總的來說,具有很好的注釋。如果您希望了解更多有關(guān) slab 緩存分配器的內(nèi)容,
建議您從源代碼開始,因為它是有關(guān)這種機制的最新文檔。 下面的 參考資料 一節(jié)提供了介紹 slab 緩
存分配器的參考資料,但是不幸的是就目前的 2.6 實現(xiàn)來說,這些文檔都已經(jīng)過時了。
========
Linux 調(diào)度器內(nèi)幕
內(nèi)核中這個非常重要的組件的最新版本改進了可伸縮性Linux? 內(nèi)核繼續(xù)不斷發(fā)展并采用新技術(shù),在可靠性、可伸縮性和性能方面獲得了長足的發(fā)展。2.6 版本
的內(nèi)核最重要的特性之一是由 Ingo Molnar 實現(xiàn)的調(diào)度器。這個調(diào)度器是動態(tài)的,可以支持負載均衡,
并以恒定的速度進行操作 —— O(1)。本文將介紹 Linux 2.6 調(diào)度器的這些屬性以及更多內(nèi)容。
本文將回顧一下 Linux 2.6 的任務(wù)調(diào)度器及其最重要的一些屬性。在深入介紹調(diào)度器的詳細信息之前,
讓我們先來理解一下調(diào)度器的基本目標。
什么是調(diào)度器?
通常來說,操作系統(tǒng)是應(yīng)用程序和可用資源之間的媒介。典型的資源有內(nèi)存和物理設(shè)備。但是 CPU 也可
以認為是一個資源,調(diào)度器可以臨時分配一個任務(wù)在上面執(zhí)行(單位是時間片)。調(diào)度器使得我們同時
執(zhí)行多個程序成為可能,因此可以與具有各種需求的用戶共享 CPU。
調(diào)度器的一個重要目標是有效地分配 CPU 時間片,同時提供很好的用戶體驗。調(diào)度器還需要面對一些互
相沖突的目標,例如既要為關(guān)鍵實時任務(wù)最小化響應(yīng)時間,又要最大限度地提高 CPU 的總體利用率。下
面我們來看一下 Linux 2.6 調(diào)度程序是如何實現(xiàn)這些目標的,并與以前的調(diào)度器進行比較。
回頁首
早期 Linux 調(diào)度器的問題
O-notation 的重要性
O-notation 可以告訴我們一個算法會占用多少時間。一個 O(n) 算法所需要的時間依賴于輸入的多少(
與 n 是線性關(guān)系),而 O(n^2) 則是輸入數(shù)量的平方。O(1) 與輸入無關(guān),可以在固定的時間內(nèi)完成操
作。
在 2.6 版本的內(nèi)核之前,當很多任務(wù)都處于活動狀態(tài)時,調(diào)度器有很明顯的限制。這是由于調(diào)度器是使
用一個復雜度為 O(n) 的算法實現(xiàn)的。在這種調(diào)度器中,調(diào)度任務(wù)所花費的時間是一個系統(tǒng)中任務(wù)個數(shù)
的函數(shù)。換而言之,活動的任務(wù)越多,調(diào)度任務(wù)所花費的時間越長。在任務(wù)負載非常重時,處理器會因
調(diào)度消耗掉大量的時間,用于任務(wù)本身的時間就非常少了。因此,這個算法缺乏可伸縮性。
在對稱多處理系統(tǒng)(SMP)中,2.6 版本之前的調(diào)度器對所有的處理器都使用一個運行隊列。這意味著一
個任務(wù)可以在任何處理器上進行調(diào)度 —— 這對于負載均衡來說是好事,但是對于內(nèi)存緩存來說卻是個
災(zāi)難。例如,假設(shè)一個任務(wù)正在 CPU-1 上執(zhí)行,其數(shù)據(jù)在這個處理器的緩存中。如果這個任務(wù)被調(diào)度到?
CPU-2 上執(zhí)行,那么數(shù)據(jù)就需要先在 CPU-1 使其無效,并將其放到 CPU-2 的緩存中。
以前的調(diào)度器還使用了一個運行隊列鎖;因此在 SMP 系統(tǒng)中,選擇一個任務(wù)執(zhí)行就會阻礙其他處理器操
作這個運行隊列。結(jié)果是空閑處理器只能等待這個處理器釋放出運行隊列鎖,這樣會造成效率的降低。
最后,在早期的內(nèi)核中,搶占是不可能的;這意味著如果有一個低優(yōu)先級的任務(wù)在執(zhí)行,高優(yōu)先級的任
務(wù)只能等待它完成。
回頁首
Linux 2.6 調(diào)度器簡介
2.6 版本的調(diào)度器是由 Ingo Molnar 設(shè)計并實現(xiàn)的。Ingo 從 1995 年開始就一直參與 Linux 內(nèi)核的開
發(fā)。他編寫這個新調(diào)度器的動機是為喚醒、上下文切換和定時器中斷開銷建立一個完全 O(1) 的調(diào)度器
。觸發(fā)對新調(diào)度器的需求的一個問題是 Java? 虛擬機(JVM)的使用。Java 編程模型使用了很多執(zhí)行線
程,在 O(n) 調(diào)度器中這會產(chǎn)生很多調(diào)度負載。O(1) 調(diào)度器在這種高負載的情況下并不會受到太多影響
,因此 JVM 可以有效地執(zhí)行。
2.6 版本的調(diào)度器解決了以前調(diào)度器中發(fā)現(xiàn)的 3 個主要問題(O(n) 和 SMP 可伸縮性的問題),還解決
了其他一些問題。現(xiàn)在我們將開始探索一下 2.6 版本的調(diào)度器的基本設(shè)計。
主要的調(diào)度結(jié)構(gòu)
首先我們來回顧一下 2.6 版本的調(diào)度器結(jié)構(gòu)。每個 CPU 都有一個運行隊列,其中包含了 140 個優(yōu)先級
列表,它們是按照先進先出的順序進行服務(wù)的。被調(diào)度執(zhí)行的任務(wù)都會被添加到各自運行隊列優(yōu)先級列
表的末尾。每個任務(wù)都有一個時間片,這取決于系統(tǒng)允許執(zhí)行這個任務(wù)多長時間。運行隊列的前 100 個
優(yōu)先級列表保留給實時任務(wù)使用,后 40 個用于用戶任務(wù)(參見圖 1)。我們稍后將來看一下為什么這
種區(qū)別非常重要。
圖 1. Linux 2.6 調(diào)度器的運行隊列結(jié)構(gòu)
Linux 2.6 調(diào)度器的運行隊列結(jié)構(gòu)
除了 CPU 的運行隊列(稱為活動運行隊列(active runqueue))之外,還有一個過期運行隊列。當活
動運行隊列中的一個任務(wù)用光自己的時間片之后,它就被移動到過期運行隊列(expired runqueue) 中
。在移動過程中,會對其時間片重新進行計算(因此會體現(xiàn)其優(yōu)先級的作用;稍后會更詳細地介紹)。
如果活動運行隊列中已經(jīng)沒有某個給定優(yōu)先級的任務(wù)了,那么指向活動運行隊列和過期運行隊列的指針
就會交換,這樣就可以讓過期優(yōu)先級列表變成活動優(yōu)先級的列表。
調(diào)度器的工作非常簡單:它在優(yōu)先級最高的隊列中選擇一個任務(wù)來執(zhí)行。為了使這個過程的效率更高,
內(nèi)核使用了一個位圖來定義給定優(yōu)先級列表上何時存在任務(wù)。因此,在大部分體系架構(gòu)上,會使用一條?
find-first-bit-set 指令在 5 個 32 位的字(140 個優(yōu)先級)中哪一位的優(yōu)先級最高。查找一個任務(wù)
來執(zhí)行所需要的時間并不依賴于活動任務(wù)的個數(shù),而是依賴于優(yōu)先級的數(shù)量。這使得 2.6 版本的調(diào)度器
成為一個復雜度為 O(1) 的過程,因為調(diào)度時間既是固定的,而且也不會受到活動任務(wù)個數(shù)的影響。
更好地支持 SMP 系統(tǒng)
那么什么是 SMP 呢?SMP 是一種體系架構(gòu),其中多個 CPU 可以用來同時執(zhí)行各個任務(wù),它與傳統(tǒng)的非
對稱處理系統(tǒng)不同,后者使用一個 CPU 來執(zhí)行所有的任務(wù)。SMP 體系架構(gòu)對多線程的應(yīng)用程序非常有益
。
盡管優(yōu)先級調(diào)度在 SMP 系統(tǒng)上也可以工作,但是它這種大鎖體系架構(gòu)意味著當一個 CPU 選擇一個任務(wù)
進行分發(fā)調(diào)度時,運行隊列會被這個 CPU 加鎖,其他 CPU 只能等待。2.6 版本的調(diào)度器不是使用一個
鎖進行調(diào)度;相反,它對每個運行隊列都有一個鎖。這樣允許所有的 CPU 都可以對任務(wù)進行調(diào)度,而不
會與其他 CPU 產(chǎn)生競爭。
另外,由于每個處理器都有一個運行隊列,因此任務(wù)通常都是與 CPU 密切相關(guān)的,可以更好地利用 CPU?
的熱緩存。
任務(wù)搶占
Linux 2.6 版本調(diào)度器的另外一個優(yōu)點是它允許搶占。這意味著當高優(yōu)先級的任務(wù)準備運行時低優(yōu)先級
的任務(wù)就不能執(zhí)行了。調(diào)度器會搶占低優(yōu)先級的進程,并將這個進程放回其優(yōu)先級列表中,然后重新進
行調(diào)度。
回頁首
但是請等一下,還有更多功能呢!
似乎 2.6 版本調(diào)度器的 O(1) 特性和搶占特性還不夠,這個調(diào)度器還提供了動態(tài)任務(wù)優(yōu)先級和 SMP 負
載均衡功能。下面就讓我們來討論一下這些功能都是什么,以及它們分別提供了哪些優(yōu)點。
動態(tài)任務(wù)優(yōu)先級
為了防止任務(wù)獨占 CPU 從而會餓死其他需要訪問 CPU 的任務(wù),Linux 2.6 版本的調(diào)度器可以動態(tài)修改
任務(wù)的優(yōu)先級。這是通過懲罰 CPU 綁定的任務(wù)而獎勵 I/O 綁定的任務(wù)實現(xiàn)的。I/O 綁定的任務(wù)通常使
用 CPU 來設(shè)置 I/O,然后就睡眠等待 I/O 操作完成。這種行為為其他任務(wù)提供了 CPU 的訪問能力。
用戶響應(yīng)能力更好
與用戶進行通信的任務(wù)都是交互型的,因此其響應(yīng)能力應(yīng)該比非交互式任務(wù)更好。由于與用戶的通信(
不管是向標準輸出上發(fā)送數(shù)據(jù),還是通過標準輸入等待輸入數(shù)據(jù))都是 I/O 綁定型的,因此提高這些任
務(wù)的優(yōu)先級可以獲得更好的交互式響應(yīng)能力。
由于 I/O 綁定型的任務(wù)對于 CPU 訪問來說是無私的,因此其優(yōu)先級減少(獎勵)最多 5 個優(yōu)先級。
CPU 綁定的任務(wù)會通過將其優(yōu)先級增加最多 5 個優(yōu)先級進行懲罰。
任務(wù)到底是 I/O 綁定的還是 CPU 綁定的,這是根據(jù)交互性 原則確定的。任務(wù)的交互性指標是根據(jù)任務(wù)
執(zhí)行所花費的時間與睡眠所花費的時間的對比程度進行計算的。注意,由于 I/O 任務(wù)先對 I/O 進行調(diào)
度,然后再進行睡眠,因此 I/O 綁定的任務(wù)會在睡眠和等待 I/O 操作完成上面花費更多的時間。這會
提高其交互性指標。
有一點值得注意,優(yōu)先級的調(diào)整只會對用戶任務(wù)進行,對于實時任務(wù)來說并不會對其優(yōu)先級進行調(diào)整。
SMP 負載均衡
在 SMP 系統(tǒng)中創(chuàng)建任務(wù)時,這些任務(wù)都被放到一個給定的 CPU 運行隊列中。通常來說,我們無法知道
一個任務(wù)何時是短期存在的,何時需要長期運行。因此,最初任務(wù)到 CPU 的分配可能并不理想。
為了在 CPU 之間維護任務(wù)負載的均衡,任務(wù)可以重新進行分發(fā):將任務(wù)從負載重的 CPU 上移動到負載
輕的 CPU 上。Linux 2.6 版本的調(diào)度器使用負載均衡(load balancing) 提供了這種功能。每隔?
200ms,處理器都會檢查 CPU 的負載是否不均衡;如果不均衡,處理器就會在 CPU 之間進行一次任務(wù)均
衡操作。
這個過程的一點負面影響是新 CPU 的緩存對于遷移過來的任務(wù)來說是冷的(需要將數(shù)據(jù)讀入緩存中)。
記住 CPU 緩存是一個本地(片上)內(nèi)存,提供了比系統(tǒng)內(nèi)存更快的訪問能力。如果一個任務(wù)是在某個?
CPU 上執(zhí)行的,與這個任務(wù)有關(guān)的數(shù)據(jù)都會被放到這個 CPU 的本地緩存中,這就稱為熱的。如果對于某
個任務(wù)來說,CPU 的本地緩存中沒有任何數(shù)據(jù),那么這個緩存就稱為冷的。
不幸的是,保持 CPU 繁忙會出現(xiàn) CPU 緩存對于遷移過來的任務(wù)為冷的情況。
回頁首
挖掘更多潛能
2.6 版本調(diào)度器的源代碼都很好地封裝到了 /usr/src/linux/kernel/sched.c 文件中。我們在表 1 中
對在這個文件中可以找到的一些有用的函數(shù)進行了總結(jié)。
表 1. Linux 2.6 調(diào)度器的功能
函數(shù)名 函數(shù)說明
schedule 調(diào)度器主函數(shù)。調(diào)度優(yōu)先級最高的任務(wù)執(zhí)行。
load_balance 檢查 CPU,查看是否存在不均衡的情況,如果不均衡,就試圖遷移任務(wù)。
effective_prio 返回任務(wù)的有效優(yōu)先級(基于靜態(tài)策略,但是可以包含任何獎勵和懲罰)。
recalc_task_prio 根據(jù)任務(wù)的空閑時間確定對任務(wù)的獎勵或懲罰。
source_load 適當?shù)赜嬎阍?CPU(任務(wù)從中遷移出的 CPU)的負載。
target_load 公平地計算目標 CPU(任務(wù)可能遷移到的 CPU)的負載。
migration_thread 在 CPU 之間遷移任務(wù)的高優(yōu)先級的系統(tǒng)線程。
運行隊列的結(jié)構(gòu)也可以在 /usr/src/linux/kernel/sched.c 文件中找到。2.6 版本的調(diào)度器還可以提供
一些統(tǒng)計信息(如果啟用了 CONFIG_SCHEDSTATS)。這些統(tǒng)計信息可以從 /proc 文件系統(tǒng)中的?
/proc/schedstat 看到,它為系統(tǒng)中的每個 CPU 都提供了很多數(shù)據(jù),包括負載均衡和進程遷移的統(tǒng)計信
息。
回頁首
展望
Linux 2.6 調(diào)度器從早先的 Linux 調(diào)度器已經(jīng)跨越了一大步。它極大地改善了最大化利用 CPU 的能力
,同時還為用戶提供了很好的響應(yīng)體驗。搶占和對多處理器體系架構(gòu)的更好支持使整個系統(tǒng)更接近于多
桌面和實時系統(tǒng)都非常有用的操作系統(tǒng)。Linux 2.8 版本的內(nèi)核現(xiàn)在談?wù)撨€為時尚早,但是從 2.6 版本
的變化中,我們可以期望會有更多的好東西。
========
相關(guān)鏈接
http://www.ibm.com/developerworks/cn/linux/l-linux-kernel/總結(jié)
以上是生活随笔為你收集整理的linux内核技术文章的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STL应用总结
- 下一篇: Linux 应用编程