版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、linux 源代碼分析 :Linux 操作系統(tǒng)源代碼詳細(xì) 分析 瘋狂代碼 http:/CrazyC ?:http:/CrazyC內(nèi)容介紹 : Linux 擁有現(xiàn)代操作系統(tǒng)所有功能如真正搶先式多任務(wù)處理、支持多用戶內(nèi)存保護(hù)虛擬內(nèi)存支持 SMP UF符合POSD標(biāo)準(zhǔn)聯(lián)網(wǎng)、圖形用戶接口和桌面環(huán)境具有快速性、穩(wěn)定性等特點(diǎn)本書(shū)通過(guò)分析Linux內(nèi)核源代碼充分揭示了 Linux 作為操作系統(tǒng)內(nèi)核是如何完成保證系統(tǒng)正常運(yùn)行、協(xié)調(diào)多個(gè)并發(fā)進(jìn)程、管理內(nèi)存等工作 現(xiàn)實(shí)中能讓人自由獲取系統(tǒng)源代碼并不多通過(guò)本書(shū)學(xué)習(xí)將大大有助于讀者編寫(xiě)自己新第部分 Linux 內(nèi)核源代碼arch/i386/kernel/entry.S
2、 2 arch/i386/kernel/init_task.c 8 arch/i386/kernel/irq.c 8 arch/i386/kernel/irq.h 19 arch/i386/kernel/process.c 22 arch/i386/kernel/signal.c 30 arch/i386/kernel/smp.c 38 arch/i386/kernel/time.c 58 arch/i386/kernel/traps.c 65 arch/i386/lib/delay.c 73 arch/i386/mm/fault.c 74 arch/i386/mm/init.c 76 fs/
3、binfmt-elf.c 82 fs/binfmt_java.c 96 fs/exec.c 98 /asm-generic/smplock.h 107 /asm-i386/atomic.h 108 /asm- i386/current.h 109 /asm-i386/dma.h 109 /asm-i386/elf.h 113 /asm-i386/hardirq.h 114 /asm- i386/page.h 114 /asm-i386/pgtable.h 115 /asm-i386/ptrace.h 122 /asm-i386/semaphore.h 123 /asm- i386/shmpar
4、am.h 124 /asm-i386/sigcontext.h 125 /asm-i386/siginfo.h 125 /asm-i386/signal.h 127 /asm-i386/smp.h 130 /asm-i386/softirq.h 132 /asm-i386/spinlock.h 133 /asm-i386/system.h 137 /asm-i386/uaccess.h 139 /binfmts.h 146 /capability.h 147 /linux/elf.h 150 /linux/elfcore.h 156 /linux/errupt.h 157 /linux/ker
5、nel.h 158 /linux/kernel_stat.h 159 /linux/limits.h 160 /linux/mm.h 160 /linux/module.h 164 /linux/msg.h 168 /linux/personality.h 169 /linux/reboot.h 169 /linux/resource.h 170 /linux/sched.h 171 /linux/sem.h 179 /linux/shm.h 180 /linux/signal.h 181 /linux/slab.h 184 /linux/smp.h 184 /linux/smp_lock.h
6、 185 /linux/swap.h 185 /linux/swapctl.h 187 /linux/sysctl.h 188 /linux/tasks.h 194 /linux/time.h 194 /linux/timer.h 195 /linux/times.h 196 /linux/tqueue.h 196 /linux/wait.h 198 init/.c 198 init/version.c 212 ipc/msg.c 213 ipc/sem.c 218 ipc/shm.c 227 ipc/util.c 236 kernel/capability.c 237 kernel/dma.
7、c 240 kernel/exec_do.c 241 kernel/exit.c 242 kernel/fork.c 248 kernel/info.c 255 kernel/itimer.c 255 kernel/kmod.c 257 kernel/module.c 259 kernel/panic.c 270 kernel/prk.c 271 kernel/sched.c 275 kernel/signal.c 295 kernel/softirq.c 307 kernel/sys.c 307 kernel/sysctl.c 318 kernel/time.c 330 mm/memory.
8、c 335 mm/mlock.c 345 mm/mmap.c 348 mm/mprotect.c 358 mm/mremap.c 361 mm/page_alloc.c 363 mm/page_io.c 368 mm/slab.c 372 mm/swap.c 394 mm/swap_state.c 395 mm/swapfile.c 398 mm/vmalloc.c 406 mm/vmscan.c 409第 2 部分 Linux 內(nèi)核源代碼分析 第 1章 Linux 介紹 讓用戶很詳細(xì)地了解大多數(shù)現(xiàn)有操作系統(tǒng)實(shí)際工作方式是 不可能大多數(shù)操作系統(tǒng)源代碼都是嚴(yán)格保密除了些研究用及為操作系統(tǒng)教學(xué)而設(shè)
9、計(jì)系統(tǒng)外盡管研究和教學(xué)目都 很好但是這類(lèi)系統(tǒng)很少能夠通過(guò)對(duì)正式操作系統(tǒng)小部分實(shí)現(xiàn)來(lái)體現(xiàn)操作系統(tǒng)實(shí)際功能對(duì)于操作系統(tǒng)些特殊問(wèn)題 這種折衷系統(tǒng)所能夠表現(xiàn)就更是少得可憐了 在以實(shí)際使用為目標(biāo)操作系統(tǒng)中讓任何人都可以自由獲取系統(tǒng)源代 碼無(wú)論目是要了解、學(xué)習(xí)還是改進(jìn)這樣現(xiàn)實(shí)系統(tǒng)并不多本書(shū)主題就是這些少數(shù)操作系統(tǒng)中個(gè) :Linux Linux 工作 方式類(lèi)似于Uinx它是免費(fèi)源代碼也是開(kāi)放符合標(biāo)準(zhǔn)規(guī)范標(biāo)準(zhǔn) 32位(在64位CPUb是64位)操作系統(tǒng)Linux擁有現(xiàn) 代操作系統(tǒng)所具有內(nèi)容例如 : * 真正搶先式多任務(wù)處理支持多用戶 * 內(nèi)存保護(hù) * 虛擬內(nèi)存 * 支持對(duì)稱多處理機(jī) SMP(symmetric
10、 multiprocess in g)即多個(gè)CP機(jī)器以及通常單CPU(UP機(jī)器*符合POSD標(biāo)準(zhǔn)* 聯(lián)網(wǎng)*圖形用戶接口和桌面環(huán)境 ( 實(shí)際上桌面環(huán)境并不只個(gè) ) * 速度和穩(wěn)定性 嚴(yán)格說(shuō)來(lái) Linux 并不是個(gè)完整操作系統(tǒng)當(dāng)我 們?cè)诎惭b通常所說(shuō)Linux時(shí)我們實(shí)際安裝是很多工具集合這些工具協(xié)同工作以組成個(gè)功能強(qiáng)大實(shí)用系統(tǒng)Linux本身只是這個(gè)操作系統(tǒng)內(nèi)核是操作系統(tǒng)心臟、靈魂、指揮中心(整個(gè)系統(tǒng)應(yīng)該稱為GNU/Linux其原因在本章后續(xù)內(nèi)容中將會(huì)給以介紹 )內(nèi)核以獨(dú)占方式執(zhí)行最底層任務(wù)保證系統(tǒng)正常運(yùn)行協(xié)調(diào)多個(gè)并發(fā)進(jìn)程管理進(jìn)程使用內(nèi)存使 它們相互的間不產(chǎn)生沖突滿足進(jìn)程訪問(wèn)磁盤(pán)請(qǐng)求等等在本書(shū)中我們給
11、大家揭示就是Linux是如何完成這具有挑戰(zhàn)性工作1.1 Linux和Unix簡(jiǎn)明歷史 為了讓大家對(duì)本書(shū)所討論內(nèi)容有更清楚了解讓我們先來(lái)簡(jiǎn)要回顧下Linux歷史由于Linux是在Unix基礎(chǔ)上發(fā)展而來(lái)我們?cè)掝}就從 Unix開(kāi)始Unix是由AT&貝爾實(shí)驗(yàn)室Ken Thompso和Dennis Ritchie于1969年在臺(tái)已經(jīng)廢棄了 PDP-7上開(kāi)發(fā);它最初是個(gè)用匯編語(yǔ)言寫(xiě)成單用戶操作 系統(tǒng)不久Thompso和Ritchie成功地說(shuō)服管理部門(mén)為他們購(gòu)買(mǎi)更新機(jī)器以便該開(kāi)發(fā)小組可以實(shí)現(xiàn)個(gè)文本處理系 統(tǒng)Unix就在PDP-1上用C語(yǔ)言重新編寫(xiě)(發(fā)明C語(yǔ)言部分目就在于此)它果真變成了個(gè)文本處理系統(tǒng)
12、一不久的后 只不過(guò)問(wèn)題是他們先實(shí)現(xiàn)了個(gè)操作系統(tǒng)而已最終他們實(shí)現(xiàn)了該文本處理工具而且Unix(以及Unix上運(yùn)行工具)也在AT&T!到廣泛應(yīng)用在1973年Thompso和Ritchie在個(gè)操作系統(tǒng)會(huì)議上就這個(gè)系統(tǒng)發(fā)表了篇論文該論 文引起了學(xué)術(shù)界對(duì)Unix系統(tǒng)極大興趣由于1956年反托拉斯法案限制AT&T不能涉足計(jì)算機(jī)業(yè)務(wù)但允許它象征 性地收取費(fèi)用發(fā)售該系統(tǒng)就這樣Un ix被廣泛發(fā)布首先是學(xué)術(shù)科研用戶后來(lái)又?jǐn)U展到政府和商業(yè)用戶伯克利加州大學(xué)是學(xué)術(shù)用戶中個(gè)在這里Unix得到了計(jì)算機(jī)系統(tǒng)研究小組(CSRG廣泛應(yīng)用并且在這里所進(jìn)行修改引發(fā)了 Unix大系列這就是廣為人知伯克利軟件 Sof
13、tware開(kāi)發(fā)(BSD)Unix除了 AT&所提供Unix系列的外BSD!最有影 響力Unix系列BSDtUnix中增加了很多顯著特性例如TCP/IP網(wǎng)絡(luò)更好用戶文件系統(tǒng)(UFS)工作控制并且改進(jìn)了 AT&內(nèi)存管理代碼多年以來(lái)BS阪本Unix直在學(xué)術(shù)環(huán)境中占據(jù)主導(dǎo)地位但最終發(fā)展成為V版本AT&TUnix則成為商業(yè)領(lǐng)域領(lǐng)頭羊從某種程度上來(lái)說(shuō)這是有社會(huì)原因:學(xué)校傾向于使用非正式但通常更好用BS風(fēng)格Unix而商 業(yè)界則傾向于從AT&獲取Unix 在用戶需求和用戶編程改進(jìn)特性促進(jìn)下 BS嘰格Unix般要比AT&TUni)更具有 創(chuàng)新性而且改進(jìn)也更為迅速但是在 A
14、T&破布最后個(gè)正式版本 V Release 4(SVR4)時(shí)V Unix已經(jīng)吸收了 BSD 多數(shù)重要優(yōu)點(diǎn)并且還增加了些自己優(yōu)勢(shì)這部分由于從1984年開(kāi)始AT&T逐漸可以將Unix商業(yè)化而伯克利Unix開(kāi)發(fā)工作在1993年 BSD4.4版本完成以后就逐漸收縮以至終止了然而 BSDS步改進(jìn)由外界開(kāi)發(fā)者延續(xù)下來(lái)到今天還 在繼續(xù)進(jìn)行正在進(jìn)行Unix系列開(kāi)發(fā)中至少有4個(gè)獨(dú)立版本是直接起源于BSD4.4這還不包括幾個(gè)廠商Unix版本例 如惠普HP-UX是部分地或者全部基于BS師發(fā)展起來(lái) 實(shí)際上Unix變種并不止BS和V由于Unix主要使用C語(yǔ) 言來(lái)編寫(xiě)這就使得它移植到新機(jī)器上相對(duì)比較容易它
15、簡(jiǎn)單性也使其重新設(shè)計(jì)和開(kāi)發(fā)相對(duì)比較容易Un ix這些特點(diǎn)大受商業(yè)界硬件供應(yīng)商歡迎比如 Sun SGI、HP IBM DEC Amdahl等等;IBM還不止次對(duì)Unix進(jìn)行了再開(kāi) 發(fā)廠商們?cè)O(shè)計(jì)開(kāi)發(fā)出新硬件并簡(jiǎn)單地將Un ix移植到新硬件上這樣新硬件經(jīng)發(fā)布便具備定功能經(jīng)過(guò)段時(shí)間的后這 些廠商都擁有了自己專有Unix版本而且為了占有市場(chǎng)這些版本故意以區(qū)別側(cè)重點(diǎn)發(fā)布出來(lái)以更好地占有用戶 版本混亂狀態(tài)促進(jìn)了標(biāo)準(zhǔn)化工作進(jìn)行其中最主要就是POSIX系列標(biāo)準(zhǔn)它定義了套標(biāo)準(zhǔn)操作系統(tǒng)接口和工具從理論上說(shuō)posi)標(biāo)準(zhǔn)代碼很容易移植到任何遵守posi)標(biāo)準(zhǔn)操作系統(tǒng)中而且嚴(yán)格posing試已經(jīng)把這種理論上可 移植性轉(zhuǎn)
16、化為現(xiàn)實(shí)直到今天幾乎所有正式操作系統(tǒng)都以支持POSIXB準(zhǔn)為目標(biāo)現(xiàn)在讓我們回顧下在1984年杰出電腦黑客Richard Stallman獨(dú)立開(kāi)發(fā)出個(gè)類(lèi)Unix操作系統(tǒng)該操作系統(tǒng)具有完全內(nèi)核、開(kāi)發(fā)工具和終端用戶應(yīng) 用在GNU("GN誷Not Unix ”首字母縮寫(xiě))計(jì)劃配合下Stallman開(kāi)發(fā)這個(gè)產(chǎn)品有自己技術(shù)理想:他想開(kāi)發(fā)出個(gè) 質(zhì)量高而且自由操作系統(tǒng) Stallman 使用了“自由” (free) 這個(gè)詞不僅意味著用戶可以免費(fèi)獲取軟件 Software ;而且更重要是它將意味著某種程度“解放” : 用戶可以自由使用、拷貝、查詢、重用、修改甚至是分 發(fā)這份軟件Software完全沒(méi)有
17、軟件Software使用限制這也正是Stallman創(chuàng)建自由軟件Software基金會(huì)(FSF)資 助GN軟件Software開(kāi)發(fā)本意(FSF也在資助其他科研方面開(kāi)發(fā)工作)15年來(lái)GNU:程已經(jīng)吸收、產(chǎn)生了大量 這不僅包括Emacs gcc(GNUC編譯器)、bash(shell命令)還有大部分Linux用戶所熟知許多應(yīng)用現(xiàn)在正在進(jìn)行 開(kāi)發(fā)項(xiàng)目是GNU Hur(內(nèi)核這是GN操作系統(tǒng)最后個(gè)主要部件(實(shí)際上Hurd內(nèi)核早已能夠使用了不過(guò)當(dāng)前版本 號(hào)為0.3系統(tǒng)在什么時(shí)候能夠完成還是未知數(shù) )盡管Linux大受歡迎但是Hurd內(nèi)核還在繼續(xù)開(kāi)發(fā)原因有幾個(gè)方面其是Hurd體系結(jié)構(gòu)十分清晰地體現(xiàn)了Stal
18、lman有關(guān)操作系統(tǒng)工作方式思想例如在運(yùn)行期間任何用戶都可以部分地改變或替換Hurd(這種替換不是對(duì)每個(gè)用戶都是可見(jiàn)而是只對(duì)申請(qǐng)修改用戶可見(jiàn)而且還必須符合規(guī)范標(biāo)準(zhǔn))另個(gè)原因是據(jù)介紹Hurd對(duì)于多處理器支持比Linux本身內(nèi)核要好還有個(gè)簡(jiǎn)單原因是興趣驅(qū)動(dòng)員們希望能夠自由地進(jìn)行自己所喜歡工作只要有人希望為 Hurd工作Hurd開(kāi)發(fā)就不會(huì)停止如果他們能夠如愿以償 Hurd有朝日將成為L(zhǎng)inux強(qiáng)勁對(duì)手不過(guò)在今天Linux還是 自由內(nèi)核王國(guó)里無(wú)可爭(zhēng)議統(tǒng)治者在GNUt展中期也就是1991年個(gè)名叫Linus Torvalds芬蘭大學(xué)生想要了解In tel新CPU- 80386他認(rèn)為比較好學(xué)習(xí)思路方法是自己
19、編寫(xiě)個(gè)操作系統(tǒng)內(nèi)核出于這種目加上他對(duì)當(dāng)時(shí)Un ix變種版本對(duì)于80386類(lèi)機(jī)器脆弱支持十分不滿他決定要開(kāi)發(fā)出個(gè)全功能、支持POSIXB準(zhǔn)、類(lèi)Unix操作系統(tǒng)內(nèi)核該系統(tǒng)吸收了 BS刖V優(yōu)點(diǎn)同時(shí)摒棄了它們?nèi)秉c(diǎn)Linus(雖然我知道我應(yīng)該稱他為T(mén)orvalds但是所有人都稱他為 Linus)獨(dú)立把這個(gè)內(nèi)核開(kāi)發(fā)到0.02版這個(gè)版本已經(jīng)可以運(yùn)行g(shù)cc、bash和很少些應(yīng)用這些就是他開(kāi)始全部工作 了后來(lái)他又開(kāi)始在因特網(wǎng)上尋求廣泛幫助不到3年LinusUnix Linux已經(jīng)升級(jí)到1.0版本它源代碼量也呈指數(shù)形式增長(zhǎng)實(shí)現(xiàn)了基本TCP/IP功能(網(wǎng)絡(luò)部分代碼后來(lái)重寫(xiě)過(guò)而且還可能會(huì)再次重寫(xiě))此時(shí)Linux就已經(jīng)
20、擁有大約10萬(wàn)用戶了 現(xiàn)在Lin ux內(nèi)核由150多萬(wàn)行代碼組成Linux也已經(jīng)擁有了大約1000萬(wàn)用戶(由于Linux可以自由獲 取和拷貝獲取具體統(tǒng)計(jì)數(shù)字是不可能兒inux內(nèi)核GNU/Linux附同GNU:具已經(jīng)占據(jù)了 Unix 50%市場(chǎng)些公司正 在把內(nèi)核和些應(yīng)用同安裝軟件Software打包在起生產(chǎn)出Linux發(fā)行版本這些公司包括Red Hat和Caldera公司現(xiàn) 在GNU/Linux已經(jīng)備受矚目得到了諸如Sun IBM SGI等公司廣泛支持SGI最近決定在其基于IntelMerced系 列機(jī)器上不再搭載自己Unix變種版本IRIX而是直接采用GNU/Linux; Linux甚至被指定
21、為Amiga將要發(fā)布新操 作系統(tǒng)基礎(chǔ)1.2 GNU 通用公共許可證 這樣個(gè)如此流行操作系統(tǒng)當(dāng)然值得我們學(xué)習(xí)按照通用公共許可證 (GPLGeneralPublic Lice nse)規(guī)定Lin ux源代碼可以自由獲取這滿足了我們學(xué)習(xí)該系統(tǒng)強(qiáng)烈愿望GP這份非同尋常軟件Software許可證充分體現(xiàn)了上面提到Stallman思想:只要用戶所做修改是同等自由用戶可以自由地使用、拷貝、 查詢、重用、修改甚至重新發(fā)布這個(gè)軟件 Software通過(guò)這種方式GP保證了 Linux(以及同許可證保證下大量其 他軟件Software)不僅現(xiàn)在自由可用而且以后經(jīng)過(guò)任何修改的后都仍然可以自由使用請(qǐng)注意這里自由并不是說(shuō)
22、沒(méi)有人靠這個(gè)軟件Software盈利有些日益興起公司比如發(fā)行最流行 Linux發(fā)行版本Red Hat就是個(gè)例子(Red Hat自從上市以來(lái)市值已經(jīng)突破數(shù)十億美元每年盈利數(shù)十萬(wàn)美元而且這些數(shù)字還在不斷增長(zhǎng))但是任何人都不能限制其他用戶涉足本軟件Software領(lǐng)域而且所做修改不能減少其自由程度本書(shū)附錄B中收錄了 GN通用公共許可證全文1.3 Linux開(kāi)發(fā)過(guò)程如上所述由于Linux是個(gè)自由軟件Software它可以免費(fèi)獲取以供學(xué)習(xí)研究Linux的所以值得學(xué)習(xí)研究是它是相當(dāng)優(yōu)秀操作系統(tǒng)如果Lin ux操作系統(tǒng)相當(dāng)糟糕那它就根本不值得我們使用也就沒(méi)有必要去研究 相關(guān)書(shū)籍Linux是個(gè)十分優(yōu)秀操作系統(tǒng)
23、還在于幾個(gè)相互關(guān)聯(lián)原因原因的在于它是基于天才思想開(kāi)發(fā)而成在學(xué)生時(shí)代就開(kāi)始推動(dòng)整個(gè)系統(tǒng)開(kāi)發(fā) Linus Torvalds 是個(gè)天才他才能不僅展現(xiàn)在編程能力方面而且組織竅門(mén)技巧也相 當(dāng)杰出Lin ux內(nèi)核是由世界上些最優(yōu)秀員開(kāi)發(fā)并不斷完善他們通過(guò)In ternet相互協(xié)作開(kāi)發(fā)理想操作系統(tǒng);他們享受著工作中樂(lè)趣而且也獲得了充分自豪感Linux優(yōu)秀另外個(gè)原因在于它是基于組優(yōu)秀概念 Unix是個(gè)簡(jiǎn)單卻非常優(yōu)秀模型在Linux創(chuàng)建的前Unix已經(jīng)有20年發(fā)展歷史Linux從Unix各個(gè)流派中不斷吸取成功經(jīng)驗(yàn)?zāi)7?Unix優(yōu)點(diǎn)拋 棄Unix缺點(diǎn)這樣做結(jié)果是Linux成為了 Unix系列中佼佼者:高速、健壯、
24、完整而且拋棄了歷史包袱然而Linux最強(qiáng)大生命力還在于其公開(kāi)開(kāi)發(fā)過(guò)程每個(gè)人都可以自由獲取內(nèi)核源每個(gè)人都可以對(duì)源加以修改而后他人也可以自 由獲取你修改后源如果你發(fā)現(xiàn)了缺陷你可以對(duì)它進(jìn)行修正而不用去乞求不知名公司來(lái)為你修正如果你有什么最 優(yōu)化或者新特點(diǎn)創(chuàng)意你也可以直接在系統(tǒng)中增加功能而不用向操作系統(tǒng)供應(yīng)商解釋你想法指望他們將來(lái)會(huì)增加 相應(yīng)功能當(dāng)發(fā)現(xiàn)個(gè)漏洞后你可以通過(guò)編程來(lái)彌補(bǔ)這個(gè)漏洞而不用關(guān)閉系統(tǒng)直到你供應(yīng)商為你提供修補(bǔ)由于你擁 有直接訪問(wèn)源代碼能力你也可以直接閱讀代碼來(lái)尋找缺陷或是效率不高代碼或是安全漏洞以防患于未然除非你是個(gè)員否則這點(diǎn)聽(tīng)起來(lái)仿佛沒(méi)有多少吸引力實(shí)際上即使你不是員這種開(kāi)發(fā)模型也將使
25、你受益匪淺這主要體現(xiàn)在 以下兩個(gè)方面 : * 可以間接受益于世界各地成千上萬(wàn)員隨時(shí)進(jìn)行改進(jìn)工作 * 如果你需要對(duì)系統(tǒng)進(jìn)行修改你可以 雇用員為你完成工作這部分人將根據(jù)你需求定義單獨(dú)為你服務(wù)可以設(shè)想這在源不公開(kāi)操作系統(tǒng)中將是什么樣子 Linux這種獨(dú)特自由流暢開(kāi)發(fā)模型已被命名為bazaar(集市模型)它是相對(duì)于cathedral(教堂)模型而言在 cathedral 模型中源代碼被鎖定在個(gè)保密小范圍內(nèi)只有開(kāi)發(fā)者 (很多情況下是市場(chǎng) )認(rèn)為能夠發(fā)行個(gè)新版本這個(gè)新 版本才會(huì)被推向市場(chǎng)這些術(shù)語(yǔ)在 Eric S. Raymond 教堂和集市 (The Cathedral and the Bazaar) 文
26、中有所介紹大 家可以在/esr/writings/找到這篇文章bazaar開(kāi)發(fā)模型通過(guò)重視實(shí)驗(yàn)征集并充分利用早期反饋對(duì)巨大數(shù)量腦力資源進(jìn)行平衡配置可以開(kāi)發(fā)出更優(yōu)秀軟件Software(順便說(shuō)下雖然Linux是最為明顯使用bazaar開(kāi)發(fā)模型例子但是它卻遠(yuǎn)不是第個(gè)使用這個(gè)模型系統(tǒng))為了確保這些無(wú)序開(kāi)發(fā)過(guò)程能夠有序地進(jìn)行 Linux采用了雙樹(shù)系統(tǒng)個(gè)樹(shù)是穩(wěn)定樹(shù)(stable tree)另個(gè)樹(shù)是非穩(wěn)定樹(shù)(unstable tree)或者開(kāi)發(fā)樹(shù)(developmenttree) 些新特性、實(shí)驗(yàn)性改進(jìn)等都將首先在開(kāi)發(fā)樹(shù)中進(jìn)行如果在開(kāi)發(fā)樹(shù)中所做改進(jìn)也可以應(yīng)用于穩(wěn)定樹(shù)那
27、么在開(kāi) 發(fā)樹(shù)中經(jīng)過(guò)測(cè)試以后在穩(wěn)定樹(shù)中將進(jìn)行相同改進(jìn)按照Linus觀點(diǎn)旦開(kāi)發(fā)樹(shù)經(jīng)過(guò)了足夠發(fā)展開(kāi)發(fā)樹(shù)就會(huì)成為新穩(wěn)定樹(shù)如此周而復(fù)始進(jìn)行下去源版本號(hào)形式為x.y.z對(duì)于穩(wěn)定樹(shù)來(lái)說(shuō)y是偶數(shù);對(duì)于開(kāi)發(fā)樹(shù)來(lái)說(shuō)y比相應(yīng)穩(wěn)定樹(shù)大(因此是奇數(shù) ) 截至到本書(shū)截稿時(shí)最新穩(wěn)定內(nèi)核版本號(hào)是 2.2.10 最新開(kāi)發(fā)內(nèi)核版本號(hào)是 2.3.12 對(duì)2.3 樹(shù)缺陷修正會(huì)回溯 影響(back-propagated)2.2樹(shù)而當(dāng)2.3樹(shù)足夠成熟時(shí)候會(huì)發(fā)展成為2.4.0(順便說(shuō)下這種開(kāi)發(fā)會(huì)比常規(guī)慣例要快每 版本所包含改變比以前更少了內(nèi)核開(kāi)發(fā)人員只需花很短時(shí)間就能夠完成個(gè)實(shí)驗(yàn)開(kāi)發(fā)周期) 及其鏡
28、像站點(diǎn)提供了最新可供內(nèi)核版本而且同時(shí)包括穩(wěn)定和開(kāi)發(fā)版本如果你愿意話不需 要很長(zhǎng)時(shí)間這些站點(diǎn)所提供最新版本中就可能包含了你部分源代碼第2章代碼初識(shí) 本章首先從較高層次介紹Linux內(nèi)核源概況這些都是大家關(guān)心些基本特點(diǎn)隨后將簡(jiǎn)要介紹些 實(shí)際代碼最后介紹如何編譯內(nèi)核2.1 Linux內(nèi)核源部分特點(diǎn)在過(guò)去段時(shí)期Linux內(nèi)核同時(shí)使用C語(yǔ)言和匯編語(yǔ)言來(lái)實(shí)現(xiàn)這兩種語(yǔ)言需要定平衡:C語(yǔ)言編寫(xiě)代碼移植性較好、易于維護(hù)而匯編語(yǔ)言編寫(xiě)則速度較快般只有在速度 是關(guān)鍵原因或者些因平臺(tái)相關(guān)特性而產(chǎn)生特殊要求 (例如直接和內(nèi)存管理硬件進(jìn)行通訊 )時(shí)才使用匯編語(yǔ)言 正如 實(shí)際中所做即使內(nèi)核并未使用C對(duì)象特性部分內(nèi)核也可以在
29、g(GNU編譯器)下進(jìn)行編譯同其他面向?qū)ο缶幊陶Z(yǔ) 言相比較相對(duì)而言C開(kāi)銷(xiāo)是較低但是對(duì)于內(nèi)核開(kāi)發(fā)人員來(lái)說(shuō)這已經(jīng)是太多了內(nèi)核開(kāi)發(fā)人員不斷發(fā)展編程風(fēng)格形成了 Linux代碼獨(dú)有特色本節(jié)將討論其中些問(wèn)題2.1.1 gcc 特性使用Linux內(nèi)核被設(shè)計(jì)為必須使用GNU編譯器gcc來(lái)編譯而不是任何種C編譯器都可以使用內(nèi)核代碼有時(shí)要使用gcc特性本書(shū)將陸續(xù)介紹其中部分些gcc特有代碼只是簡(jiǎn)單地使用gcc語(yǔ)言擴(kuò)展例如允許在C(不只是C)中使用inline關(guān)鍵字指示內(nèi)聯(lián)也就是說(shuō)代碼中被在每次 時(shí)都會(huì)被擴(kuò)充因而就可以節(jié)約實(shí)際開(kāi)銷(xiāo)般情況下代碼編寫(xiě)方式比較復(fù)雜對(duì)于某些類(lèi)型輸入gcc能夠產(chǎn)生比其他輸入效率更高執(zhí)行代碼從
30、理論上講編譯器可以優(yōu)化具有相同功能兩種對(duì)等思路方法并且得到相同結(jié)果因此代碼 編寫(xiě)方式是無(wú)關(guān)緊要但在實(shí)際上用某種思路方法編寫(xiě)所產(chǎn)生代碼要比用另外些思路方法編寫(xiě)所產(chǎn)生代碼執(zhí)行速 度快許多內(nèi)核開(kāi)發(fā)人員知道怎樣才能產(chǎn)生更高效執(zhí)行代碼這不斷地在他們編寫(xiě)代碼中反映出來(lái)例如考慮內(nèi)核中經(jīng)常使用goto語(yǔ)句一為了提高速度內(nèi)核中經(jīng)常大量使用這種般要避免使用語(yǔ)句在本書(shū)中所包含不到40 000行代碼中共有500多條goto語(yǔ)句大約是每80行個(gè)除匯編文件外精確統(tǒng)計(jì)數(shù)字是接近每72行個(gè)goto語(yǔ)句公平地說(shuō)這是選擇偏向結(jié)果:比例如此高原因的是本書(shū)中涉及是內(nèi)核源核心在這里速度比其他原因都需要優(yōu)先考慮整個(gè)內(nèi)核比 例大概是每26
31、0行個(gè)goto語(yǔ)句然而這仍然是我不再使用Basic進(jìn)行編程以來(lái)見(jiàn)過(guò)使用goto頻率最高地方代碼必需受特定編譯器限制特性不僅和普通應(yīng)用開(kāi)發(fā)有很大區(qū)別而且也區(qū)別于大多數(shù)內(nèi)核開(kāi)發(fā)大多數(shù)開(kāi)發(fā)人員使用C語(yǔ)言編寫(xiě)代碼來(lái)保持較高可移植性即使在編寫(xiě)操作系統(tǒng)時(shí)也是如此這樣做優(yōu)點(diǎn)是顯而易見(jiàn)最為重要點(diǎn)是旦出現(xiàn)更 好編譯器員們可以隨時(shí)進(jìn)行更換內(nèi)核對(duì)于gcc特性完全依賴使得內(nèi)核向新編譯器上移植更加困難最近Linus對(duì)這問(wèn)題在有關(guān)內(nèi)核郵件列表上表明了自己觀點(diǎn):“記住編譯器只是個(gè)工具”這是對(duì)依賴于gcc特性個(gè)很好基本思想表述 : 編譯器只是為了完成工作如果通過(guò)遵守標(biāo)準(zhǔn)還不能達(dá)到工作要求那么就不是工作要求有問(wèn)題而是對(duì)于標(biāo) 準(zhǔn)
32、依賴有問(wèn)題 在大多數(shù)情況下這種觀點(diǎn)是不能被人所接受通常情況下為了保證和語(yǔ)言標(biāo)準(zhǔn)致開(kāi)發(fā)人員可能需要 犧牲某些特性、速度或者其他相關(guān)原因其他選擇可能會(huì)為后期開(kāi)發(fā)造成很大麻煩但是在這種特定情況下Linus是正確Linux內(nèi)核是個(gè)特例其執(zhí)行速度要比向其他編譯器可移植性遠(yuǎn)為重要如果設(shè)計(jì)目標(biāo)是編寫(xiě)個(gè)可移植 性好而不要求快速運(yùn)行內(nèi)核或者是編寫(xiě)個(gè)任何人都可以使用自己喜歡編譯器進(jìn)行編譯內(nèi)核那么結(jié)論就可能會(huì)有 所區(qū)別了;而這些恰好不是Linux設(shè)計(jì)目標(biāo)實(shí)際上gcc幾乎可以為所有能夠運(yùn)行LinuxCPU生成代碼因此對(duì)于 gcc依賴并不是可移植性嚴(yán)重障礙在第3章中我們將對(duì)內(nèi)核設(shè)計(jì)目標(biāo)進(jìn)行詳細(xì)介紹說(shuō)明2.1.2 內(nèi)核代
33、碼習(xí)慣用語(yǔ) 內(nèi)核代碼中使用了些顯著習(xí)慣用語(yǔ)本節(jié)將介紹常用幾個(gè)當(dāng)通讀源代碼時(shí)真正重要問(wèn) 題并不在這些習(xí)慣用語(yǔ)本身而是這種類(lèi)型習(xí)慣用語(yǔ)確存在而且是不斷被使用和發(fā)展如果你需要編寫(xiě)內(nèi)核代碼你 應(yīng)該注意到內(nèi)核中所使用習(xí)慣用語(yǔ)并把這些習(xí)慣用語(yǔ)應(yīng)用到你代碼中當(dāng)通讀本書(shū)(或者代碼)時(shí)看看你還能找到多少習(xí)慣用語(yǔ) 為了討論這些習(xí)慣用語(yǔ)我們首先需要對(duì)它們進(jìn)行命名為了便于討論筆者創(chuàng)造了這些名字而在實(shí)際中 大家不定非要參考這些用語(yǔ)它們只是對(duì)內(nèi)核工作方式描述而已 個(gè)普通習(xí)慣用語(yǔ)筆者稱的為“資源獲取 ”(resource acquisition idiom)在這個(gè)用語(yǔ)中個(gè)必須實(shí)現(xiàn)系列資源獲取包括內(nèi)存、鎖等等(這些資源類(lèi)型未
34、必相同)只有成功地獲取當(dāng)前所需要資源的后才能處理后面資源請(qǐng)求最后該還必須釋放所有已經(jīng)獲取資源而不必考慮 沒(méi)有獲取資源 我采用“變量”這用語(yǔ) (error variable idiom) 來(lái)輔助介紹說(shuō)明資源獲取用語(yǔ)它使用個(gè)臨時(shí)變量來(lái) 記錄期望返回值當(dāng)然相當(dāng)多都能實(shí)現(xiàn)這個(gè)功能但是變量區(qū)別點(diǎn)在于它通常是用來(lái)處理由于速度原因而變得非常 復(fù)雜流程控制中問(wèn)題變量有兩個(gè)典型值 0(表示成功)和負(fù)數(shù)(表示有錯(cuò))如果執(zhí)行到標(biāo)號(hào)out2則都已經(jīng)獲取了 r1和 r2資源而且也都需要進(jìn)行釋放如果執(zhí)行到標(biāo)號(hào) out1(不管是順序執(zhí)行還是使用goto語(yǔ)句進(jìn)行跳轉(zhuǎn)到)則r2資源是 無(wú)效(也可能剛被釋放)但是r1資源卻是有效
35、而且必需在此將其釋放同理如果標(biāo)號(hào)out能被執(zhí)行則r1和r2資源都無(wú)效err所返回是或成功標(biāo)志在這個(gè)簡(jiǎn)單例子中對(duì)err些賦值是沒(méi)有必要在實(shí)戰(zhàn)中實(shí)際代碼必須遵守這種模式這樣做原因主要在于同行中可能包含有多種測(cè)試而這些測(cè)試應(yīng)該返回相同代碼因此對(duì)變量統(tǒng)賦值要比多次賦值更為 簡(jiǎn)單雖然在這個(gè)例子中對(duì)于這種屬性必要性并不非常迫切但是我還是傾向于保留這種特點(diǎn)有關(guān)實(shí)際應(yīng)用可以參 考sys_shmctl(第21654行)在第9章中還將詳細(xì)介紹這個(gè)例子2.1.3減少#和#def使用現(xiàn)在Linux內(nèi)核已經(jīng)移植到區(qū)別平臺(tái)上但是我們還必須解決移植過(guò)程中所出現(xiàn)問(wèn)題大部分支持各種區(qū)別平臺(tái)代碼由于包含許多預(yù)處理代 碼而已經(jīng)變得
36、非常不規(guī)范標(biāo)準(zhǔn)例如:這個(gè)例子試圖實(shí)現(xiàn)操作系統(tǒng)可移植性雖然 Linux關(guān)注焦點(diǎn)很明顯是實(shí)現(xiàn)代碼 在各種CPUb可移植性但是2者基本原理是致對(duì)于這類(lèi)問(wèn)題來(lái)說(shuō)預(yù)處理器是種解決方式這些雜亂問(wèn)題使得代碼 晦澀難懂更為糟糕是增加對(duì)新平臺(tái)支持有可能要求重新遍歷這些雜亂分布低質(zhì)量代碼段 (實(shí)際上你很難能找到這 類(lèi)代碼段全部)和現(xiàn)有方式區(qū)別是Linux般通過(guò)簡(jiǎn)單(或者是宏)來(lái)抽象出區(qū)別平臺(tái)間差異內(nèi)核移植可以通過(guò)實(shí)現(xiàn) 適合于相應(yīng)平臺(tái) (或宏)來(lái)實(shí)現(xiàn)這樣不僅使代碼主體簡(jiǎn)單易懂而且在移植過(guò)程中還可以比較容易地自動(dòng)檢測(cè)出你沒(méi) 有注意到內(nèi)容:如引用未聲明時(shí)會(huì)出現(xiàn)鏈接有時(shí)用預(yù)處理器來(lái)支持區(qū)別體系結(jié)構(gòu)但這種方式并不常用而相對(duì)
37、于代 碼風(fēng)格變化就更是微不足道了順便說(shuō)下我們可以注意到這種解決思路方法和使用用戶對(duì)象(或者C語(yǔ)言中充滿指針struct結(jié)構(gòu))來(lái)代替離散switch語(yǔ)句處理區(qū)別類(lèi)型思路方法十分相似在某些層次上這些問(wèn)題和解決思路方法是 統(tǒng) 可移植性問(wèn)題并不僅限于平臺(tái)和 CP移植編譯器也是個(gè)重要問(wèn)題此處為了簡(jiǎn)化假設(shè)Linux只使用gcc來(lái)編譯由于Linux只使用同個(gè)編譯器所以就沒(méi)有必要使用 #塊(或者#def塊)來(lái)選擇區(qū)別編譯器內(nèi)核代碼主要使用#def來(lái)區(qū)分需要編譯或不需要編譯部分從而對(duì)區(qū)別結(jié)構(gòu)提供支持例如代碼經(jīng)常測(cè)試SM宏是否定義過(guò)從而決定是否支持SM機(jī)2.2代碼樣例了解Linux代碼風(fēng)格最好思路方法就是實(shí)際研究
38、下它部分代碼即使你不完全理解本節(jié)所討論代碼細(xì)節(jié)也無(wú)關(guān)緊要畢竟本節(jié)主要目不是理解代碼些讀者可以只對(duì)本節(jié)進(jìn)行瀏覽本節(jié)主要目是讓讀者對(duì)Linux代碼進(jìn)行初步了解為今后工作提供必要基礎(chǔ)該討論將涉及部分廣泛使用內(nèi)核代碼 2.2.1 prk prk(25836行)是內(nèi)核內(nèi)部消息日志記錄在出現(xiàn)諸如內(nèi)核檢測(cè)到其數(shù)據(jù)結(jié)構(gòu)出現(xiàn)不致事件時(shí)內(nèi)核會(huì)使用 prk 把相關(guān)信息打印到系統(tǒng)控制臺(tái)上 對(duì)于prk般分為如下幾類(lèi):* 緊急事件(emergency)例如panic(25563行)多次使用了 prk當(dāng)內(nèi)核檢測(cè)到發(fā)生不 可恢復(fù)內(nèi)部時(shí)就會(huì)panic然后盡其所能地安全關(guān)閉計(jì)算機(jī)這個(gè)中prk以提示用戶系統(tǒng)將要關(guān)閉*調(diào)試一從 38
39、16行開(kāi)始#def塊使用prk來(lái)打印SM邏輯單元(box)中每個(gè)處理器相關(guān)配置信息但是此過(guò)程只有在使用 SMP_DEB標(biāo)志編譯代碼情況下才能夠被執(zhí)行*普通信息一例如當(dāng)機(jī)器啟動(dòng)時(shí)內(nèi)核必須估計(jì)系統(tǒng)速度以確保設(shè)備驅(qū)動(dòng)能夠忙等待 (busy-wait) 個(gè)精確極短周期計(jì)算這種估計(jì)值名為 calibrate_delay(19654 行) 它既在 19661行使用prk聲明馬上開(kāi)始計(jì)算又在19693行報(bào)告計(jì)算結(jié)果另外在第4章將詳細(xì)介紹calibrate_delay 如果你 已經(jīng)瀏覽過(guò)這些參照行你可能已經(jīng)注意到prk和prf參數(shù)十分類(lèi)似:個(gè)格式化串后跟零個(gè)或者多個(gè)參數(shù)加入串中格式化串可能是以組“”開(kāi)始這里N
40、是從0到7數(shù)字包括0和7在內(nèi)數(shù)字區(qū)分了消息日志等級(jí)(log level)只有當(dāng)日志等級(jí)高于當(dāng)前控制臺(tái)定義日志等級(jí) (console_loglevel25650 行)時(shí)才會(huì)打印消息 root 可以通過(guò)適當(dāng)減小控制臺(tái)日 志等級(jí)來(lái)過(guò)濾不是很緊急消息如果內(nèi)核在格式化串中檢測(cè)不到日志等級(jí)序列那么就會(huì)直打印消息 (實(shí)際上日志等 級(jí)序列并不定要在格式化串中出現(xiàn)可以在格式化文本中查找到它代碼 )從14946行開(kāi)始#塊介紹說(shuō)明了這些特殊序列這些定義可以幫助者正確區(qū)分對(duì)prk簡(jiǎn)單地說(shuō)我稱日志等級(jí)0到4為“緊急事件”等級(jí)5到等級(jí)6為“普通信 息”等級(jí)7自然就是我所說(shuō)“調(diào)試” (這種分類(lèi)思路方法并不意味著其他更好分類(lèi)
41、思路方法沒(méi)有用處而只是目前 我們還不關(guān)心它而已 )在上面討論基礎(chǔ)上我們研究下代碼本身prk 25836:參數(shù)fmt是prf類(lèi)型格式化串如果你對(duì)“”部分內(nèi)容不熟悉那就 需要參閱本好C語(yǔ)言參考書(shū)(在其索引中查找“變參variadic function ”)另外在安裝GNU/Linux中 stdarg幫助里也包含了個(gè)有關(guān)變參簡(jiǎn)明描述在這兒只需要敲入“man stdarg ”就可以看到 簡(jiǎn)單地說(shuō)“”部分提示編譯器fmt后面可能緊跟著數(shù)量不定任何類(lèi)型參數(shù)由于這些參數(shù)在編譯時(shí)候還沒(méi)有類(lèi)型和名字內(nèi)核使用由 3個(gè)宏va_start、va_arg和va_end組成特殊組及個(gè)特殊類(lèi)型一va_list對(duì)它們進(jìn)行處理
42、 25842:msg_level記錄了 當(dāng)前消息日志等級(jí)它是靜態(tài)這看起來(lái)可能會(huì)有些奇怪一為什么下次對(duì)prk需要記錄日志等級(jí)呢?問(wèn)題答案是只有打印出新行(n)或者賦給個(gè)新日志等級(jí)序列以后當(dāng)前消息才會(huì)結(jié)束這樣通過(guò)在包含消息結(jié)束新行里prk就保證了在多個(gè)短期沖突情況下者只打印唯個(gè)長(zhǎng)消息25845:在SM邏輯單元中內(nèi)核可能試圖從區(qū)別CPU向控制臺(tái)同時(shí)打印信息(有時(shí)在單處理機(jī)(UP)邏輯單元中也會(huì)發(fā)生同樣問(wèn)題但由于中斷還未被覆蓋掉所以問(wèn)題也并不十分明顯 ) 如果不進(jìn)行任何協(xié)同話結(jié)果就將處于完全無(wú)法讓人了解雜亂無(wú)章?tīng)顟B(tài)每個(gè)消息各個(gè)部分都和其他消息各個(gè)部分 混雜交織在起 相反內(nèi)核使用旋轉(zhuǎn)鎖 (spin-lo
43、ck) 來(lái)控制對(duì)控制臺(tái)訪問(wèn)旋轉(zhuǎn)鎖將在第 10章進(jìn)行深入介紹如果你對(duì)flags 在傳送給 spin_lock_irqsave 的前為什么不對(duì)它化感到疑惑請(qǐng)不要擔(dān)心 :spin_lock_irqsave( 對(duì)于區(qū)別版本請(qǐng) 分別參看12614行12637行 12716行和12837行)是個(gè)宏而不是個(gè)該宏實(shí)際上是將值寫(xiě)入flags中而不是從flags中 讀出值(在25895行中在flags中信息被spin_unlock_irqrestore回讀請(qǐng)參看12616行12639行12728行和12841行)25846:化變量args該變量代表prk參數(shù)中“”部分25848:內(nèi)核自身vsprf(為節(jié)省空間而省
44、略)實(shí)現(xiàn) 該功能和標(biāo)準(zhǔn)vsprf非常相似向buf中寫(xiě)入格式化文本(25634行)并返回寫(xiě)入串長(zhǎng)度(長(zhǎng)度不包括最后位終止0字節(jié) )很快你將可以看到為什么這種機(jī)制會(huì)忽略buf前3個(gè)(正如25847行注釋中所述)我們應(yīng)該注意到在這里并沒(méi)有采取嚴(yán)格措施來(lái)保證緩沖器不會(huì)過(guò)載這里系統(tǒng)假定1024個(gè)長(zhǎng)度buf已經(jīng)足夠使用(參閱25634行)如果內(nèi)核在這里能夠使用vsnprf話情況就會(huì)好許多然而vsnprf還有另外個(gè)參數(shù)限制了它能夠?qū)懭刖彌_器長(zhǎng)度25849:計(jì)算buf中最近使用元素va_end終止對(duì)“”參數(shù)處理25851:開(kāi)始格式化消息循環(huán)其中存在個(gè)內(nèi)部循環(huán)能夠處理更多內(nèi) 容(這點(diǎn)隨后就能看到)因此每次內(nèi)循環(huán)
45、開(kāi)始都開(kāi)始個(gè)新打印行由于通常情況下prk只用于打印單行所以在每次中這種循環(huán)通常只執(zhí)行次 25853:如果預(yù)先不知道消息日志等級(jí)prk會(huì)檢查當(dāng)前行是否以日志等級(jí)序列開(kāi)頭 25860:如果不是buf中開(kāi)始未使用3個(gè)就能夠起作用了(第次以后每次循環(huán)都會(huì)覆蓋部分消息文本但是這樣并不 會(huì)引起問(wèn)題這里文本只是前面行中部分它們已經(jīng)被打印過(guò)而且以后也不再需要了 )這樣就可以將日志等級(jí)插入 buf中25866:此處有如下屬性:p指向日志等級(jí)序列(消息文本緊隨其后)msg指向消息文本一請(qǐng)注意25852行和 25865行中對(duì)msg賦值 由于已知p用來(lái)指示日志等級(jí)序列開(kāi)頭一該日志等級(jí)序列可能是由自身所創(chuàng)建日志等級(jí) 可
46、以從p中抽出并存到msg_level中25868:沒(méi)有檢測(cè)到新行清空l(shuí)ine_feed標(biāo)志25869:這是前面談到過(guò)內(nèi)循環(huán) 循環(huán)將運(yùn)行到本行結(jié)束 (也就是檢測(cè)到新行標(biāo)志 )或者緩沖器末尾為止25870:除了將消息打印到控制臺(tái)的外prk還能夠記錄最近打印長(zhǎng)度為L(zhǎng)OG_ BUF_LE組(LOG_BUF_LEN16K請(qǐng)參看25632行)如果在控制臺(tái)打開(kāi)的前內(nèi)核就已經(jīng)prk則顯然不能在控制臺(tái)上正確打印消息但是這些消息將 被盡可能地到log_buf中(25656行)當(dāng)控制臺(tái)打開(kāi)以后緩存Cache在log_buf中數(shù)據(jù)就可以轉(zhuǎn)儲(chǔ)并在控制臺(tái)上打印 出來(lái)請(qǐng)參看25988行l(wèi)og_buf是個(gè)循環(huán)緩沖器log_s
47、tart和log_size變量(25657行和25646行)分別記錄當(dāng)前緩沖 器開(kāi)始位置和長(zhǎng)度本行中按位和(AND臊作實(shí)際上是快速求模(%)運(yùn)算它正確性依賴于LOG_BUF_LE值是2幕 25872:保存變量跟蹤記錄循環(huán)日志值顯然日志大小會(huì)不斷增長(zhǎng)直至達(dá)到LOG_BUF_L值為止此后log_size將保持不變而插入新將導(dǎo)致log_start增長(zhǎng)25878:請(qǐng)注意logged_chars(25658行)記錄從機(jī)器啟動(dòng)的后由prk寫(xiě)入所 有長(zhǎng)度它在每次循環(huán)中都會(huì)被更新而不是在循環(huán)結(jié)束后才改變次基于同樣道理log_start和log_size處理方式也是樣這實(shí)際上是種優(yōu)化時(shí)機(jī)本書(shū)將在結(jié)束對(duì)介紹的后再
48、對(duì)它進(jìn)行詳細(xì)討論 25879: 消息被分為若干行這當(dāng)然要 使用新行標(biāo)志符來(lái)進(jìn)行分割旦內(nèi)核檢測(cè)到新行標(biāo)志符就寫(xiě)入個(gè)完整行從而內(nèi)循環(huán)執(zhí)行也可以提前終止25884:在這里我們先不考慮內(nèi)部循環(huán)是否會(huì)提前退出從msg到 p序列是專門(mén)提供給控制臺(tái)使用(這種序列我稱的為行但是不要忘了這里行可能并不意味著新行終止buf也許還沒(méi)有終止)如果該行日志等級(jí)高于系統(tǒng)控制臺(tái)定義日志等級(jí)而且當(dāng)前又有控制臺(tái)可供打印那么就能夠正確打印該行(記住prk可能在所有控制臺(tái)打開(kāi)的前就已經(jīng)被過(guò)了)如果在該消息塊中沒(méi)有發(fā)現(xiàn)日志等級(jí)序列并且在前面prk中也沒(méi)有對(duì)msg_level賦值那么本行中msg_level就是-1由于console_
49、loglevel總不小于1(除非root通過(guò)sysctl接口鎖定)于是總是可以打印這些行 25886:本行應(yīng)該能夠被打印prk通過(guò)遍歷打開(kāi)控制臺(tái)驅(qū)動(dòng)鏈表告知每個(gè)控制臺(tái)驅(qū)動(dòng)去打印當(dāng)前行設(shè)備驅(qū)動(dòng)在本 書(shū)討論范圍的外因此控制臺(tái)驅(qū)動(dòng)代碼則并不包含在內(nèi))25888:請(qǐng)注意這里消息文本開(kāi)頭使用是msg而不是p這樣就在沒(méi)有日志等級(jí)序列情況下寫(xiě)入消息了然而日志等級(jí)序列已經(jīng)被存儲(chǔ)到log_buf緩沖器中了這樣就使后來(lái)能夠訪問(wèn)log_buf以獲取消息日志等級(jí)代碼(請(qǐng)參看25998行)不會(huì)再產(chǎn)生顯示混亂信息序列現(xiàn)象25892:如果內(nèi)層for循環(huán)發(fā)現(xiàn)新行那么buf中剩余(如果有話)將被認(rèn)為是新消息因此msg_leve
50、l會(huì)被重置但是無(wú)論怎樣外層循環(huán)都 會(huì)持續(xù)到buf清空為止25895:釋放在25845行獲取控制臺(tái)鎖(console lock) 25896:喚醒等待被寫(xiě)入控制臺(tái)日志所有進(jìn)程注意即使沒(méi)有文本被實(shí)際寫(xiě)入任何控制臺(tái)這個(gè)過(guò)程也仍然會(huì)發(fā)生這樣處理是正確無(wú)論是否要往控制臺(tái) 中寫(xiě)入文本等待進(jìn)程實(shí)際上都是在等待從log_buf中讀出信息在25748行進(jìn)程被轉(zhuǎn)入休眠狀態(tài)以等待log_buf活 動(dòng)在休眠、喚醒和等待隊(duì)列中所使用機(jī)制將在下節(jié)中進(jìn)行討論 25897: 返回日志中寫(xiě)入長(zhǎng)度如果對(duì)于每個(gè)處理工作都能減少點(diǎn)那么從25869亍開(kāi)始for循環(huán)就執(zhí)行得更快點(diǎn)當(dāng)循環(huán)存在時(shí)我們可以通過(guò)只 在循環(huán)退出時(shí)將 logged_
51、chars 更新次來(lái)稍微提高運(yùn)行速度然而我們還可以通過(guò)其他努力來(lái)提高速度由于我們可 以預(yù)知消息長(zhǎng)度因此log_size和log_start可以到最后再增長(zhǎng)讓我們來(lái)實(shí)驗(yàn)下這樣能否提高速度下面是段經(jīng)過(guò)理 想優(yōu)化代碼 : 請(qǐng)注意循環(huán)通常只需要執(zhí)行次只有在 log_buf 末尾寫(xiě)入信息需要折行時(shí)才會(huì)多次執(zhí)行因而 log_size和log_buf只需要更新次(或者當(dāng)寫(xiě)入需要換行時(shí)是兩次)這時(shí)速度確提高了但是有兩個(gè)原因使我們并不 能這樣做首先內(nèi)核可能有自己特有 memcp我們必須確保對(duì)memcp不會(huì)再次進(jìn)入對(duì)prk(有部分內(nèi)核移植版定 義了自己特有速度較快memcp版本因此所有移植都要在這點(diǎn)上保持致)如果
52、memecpypr來(lái)報(bào)告失敗那么就有 可能觸發(fā)無(wú)限循環(huán)然而在這點(diǎn)上也并不是真無(wú)藥可救使用這種解決方案最大問(wèn)題在于該內(nèi)核循環(huán)形式中也要留意新行標(biāo)志符因此使用memcp將整個(gè)消息拷貝到log_buf中是不正確:如果此處存在新行我們將無(wú)法對(duì)其進(jìn)行處理我們可以試驗(yàn)個(gè)箭雙雕辦法下面這種替代嘗試雖然可能比前面那種初步解決思路方法速度要慢但是它保持了內(nèi)核版本語(yǔ)意: (請(qǐng)注意gcc優(yōu)化器十分靈敏它足以能檢測(cè)到循環(huán)內(nèi)部表達(dá)式log_buf+LOG_BUF_LE并沒(méi)有改變因此在上面循 環(huán)中試圖手工加速計(jì)算是沒(méi)有任何效果 ) 不幸是這種思路方法并不能比現(xiàn)在內(nèi)核版本在速度上快許多而且那樣 會(huì)使得代碼晦澀難懂(如果你編
53、寫(xiě)過(guò)更新log_size和log_start代碼你就能清楚地了解這點(diǎn))你可以自己決定這種折 衷是否值得然而無(wú)論怎樣我們學(xué)到了些東西通常不管成功和否改進(jìn)內(nèi)核代碼都可以加深你對(duì)內(nèi)核工作原理理解2.2.2 等待隊(duì)列 前節(jié)我們?cè)?jiǎn)要提到進(jìn)程 (也就是正在運(yùn)行)可以轉(zhuǎn)入休眠狀態(tài)以等待某個(gè)特定事件當(dāng)該事件發(fā) 生時(shí)這些進(jìn)程能夠被再次喚醒內(nèi)核實(shí)現(xiàn)這功能技術(shù)要點(diǎn)是把等待隊(duì)列 (wait queue) 和每個(gè)事件聯(lián)系起來(lái)需要等 待事件進(jìn)程在轉(zhuǎn)入休眠狀態(tài)后插入到隊(duì)列中當(dāng)事件發(fā)生的后內(nèi)核遍歷相應(yīng)隊(duì)列喚醒休眠任務(wù)讓它投入運(yùn)行狀態(tài) 任務(wù)負(fù)責(zé)將自己從等待隊(duì)列中清除 等待隊(duì)列功能強(qiáng)大得令人吃驚它們被廣泛應(yīng)用于整個(gè)內(nèi)核中更重要
54、是實(shí)現(xiàn)等 待隊(duì)列代碼量并不大 1. wait_queue 結(jié)構(gòu) 18662: 簡(jiǎn)單數(shù)據(jù)結(jié)構(gòu)就是等待隊(duì)列節(jié)點(diǎn)它包含兩個(gè)元素 : * task 指 向struct task_struct結(jié)構(gòu)指針?biāo)韨€(gè)進(jìn)程從16325行開(kāi)始struct task_struct結(jié)構(gòu)將在第7章中進(jìn)行介紹*next 指向隊(duì)列中下節(jié)點(diǎn)指針因而等待隊(duì)列實(shí)際上是個(gè)單鏈表通常我們用指向等待隊(duì)列隊(duì)首指針來(lái)表示等待隊(duì)列例如prk使用等待隊(duì)列l(wèi)og_wait(25647行)2. wait_event 16840:通過(guò)使用這個(gè)宏內(nèi)核代碼能夠使當(dāng)前執(zhí)行進(jìn)程在等待隊(duì)列wq中等待直至給定condition(可能是任何表達(dá)式)得到滿足1684
55、2:如果條件已經(jīng)為真當(dāng)前進(jìn)程 顯然也就無(wú)需等待了 16844: 否則進(jìn)程必須等待給定條件轉(zhuǎn)變?yōu)檎孢@可以通過(guò) _wait_event 來(lái)實(shí)現(xiàn)(16824行)我 們將在下節(jié)介紹它由于_wait_event已經(jīng)同wait_event分離已知條件為假部分內(nèi)核代碼可以直接 _wait_queue而不用通過(guò)宏來(lái)進(jìn)行冗余(特別是在這些情況下)測(cè)試實(shí)際上也沒(méi)有代碼會(huì)真正這樣處理更為重要 是如果條件已經(jīng)為真wait_event會(huì)跳過(guò)將進(jìn)程插入等待隊(duì)列代碼注意wait_event主體是用個(gè)比較特殊結(jié)構(gòu)封閉起來(lái): 奇怪是這個(gè)小竅門(mén)技巧并沒(méi)有得到應(yīng)有重視這里主要思路是使被封閉代碼能夠像個(gè)單句樣使用考慮下 面這個(gè)宏該宏
56、目是如果p是個(gè)非空指針則free:除非你在如下所述情況下使用FREE否則所有都是正確有效:FREE經(jīng)擴(kuò)展以后就和(FREE1聯(lián)系在起 有些員通過(guò)如下途徑解決這種問(wèn)題:這兩種思路方法都不盡人意員在 宏以后自然而然使用分號(hào)會(huì)把擴(kuò)展信息弄亂以 FREE為例在宏展開(kāi)的后為了使編譯器能更準(zhǔn)確地識(shí)別我們還需要進(jìn)行定縮進(jìn)調(diào)節(jié)最終代碼如下所示:這樣就會(huì)引起語(yǔ)法一和任何個(gè)都不匹配 FREE從本質(zhì)上講也存在同樣問(wèn) 題而且在研究問(wèn)題產(chǎn)生原因同時(shí)就能夠明白為什么宏體里是否包含是無(wú)關(guān)緊要不管宏體內(nèi)部?jī)?nèi)容如何只要使用 組括號(hào)來(lái)指定宏體就會(huì)碰到相同問(wèn)題弓I入do/while(0)竅門(mén)技巧能夠克服前面所出現(xiàn)所有問(wèn)題現(xiàn)在我們可
57、以編寫(xiě)FREE4將FREE和其他宏樣插入相同代碼的后這段代碼當(dāng)然可以正確執(zhí)行編譯器能夠優(yōu)化這個(gè)偽循環(huán)舍棄循 環(huán)控制因此執(zhí)行代碼并沒(méi)有速度損失我們也從而得到了能夠?qū)崿F(xiàn)理想功能宏 雖然這是個(gè)可以接受解決方案但是 我們不能不提到是編寫(xiě)要比編寫(xiě)宏好得多不過(guò)如果你不能提供所需開(kāi)銷(xiāo)那么就需要使用內(nèi)聯(lián)這種情況雖然在內(nèi) 核中經(jīng)常出現(xiàn)但是在其他地方就要少得多(不可否認(rèn)當(dāng)使用C gcc或者任何實(shí)現(xiàn)了將要出現(xiàn)修正版ISO標(biāo)準(zhǔn)C編 譯器時(shí)這種方案只是種選擇就是最后為 C增加內(nèi)聯(lián))3. _wait_event 16824:_wait_event使當(dāng)前進(jìn)程在等待隊(duì)列wq中等待直至condition為真16829:通過(guò)ad
58、d_wait_queue(16791行)局部變量_wait可以被鏈接到隊(duì)列上 注意_wait是在堆棧中而不是在內(nèi)核堆中分配空間這是內(nèi)核中常用種竅門(mén)技巧在宏運(yùn)行結(jié)束的前_wait就已經(jīng)被從等待隊(duì)列中移走了因此等待隊(duì)列中指向它指針總是有效16830:重復(fù)分配CP給另個(gè)進(jìn)程直至條件滿足這點(diǎn)將在下面幾節(jié)中討論 16831:進(jìn)程被置為T(mén)ASK_UNINTERRUPTIBL態(tài)(16190行)這意味著進(jìn)程處于休眠狀 態(tài)不應(yīng)被喚醒即使是信號(hào)也不能打斷該進(jìn)程休眠信號(hào)在第6章中介紹而進(jìn)程狀態(tài)則在第 7章中介紹 16832: 如果條件已經(jīng)滿足則可以退出循環(huán) 請(qǐng)注意如果在第次循環(huán)時(shí)條件就已經(jīng)滿足那么前面行賦值就浪費(fèi)了 (在循環(huán)結(jié)束 的后進(jìn)程狀態(tài)會(huì)立刻被再次賦值 )_wait_event 假定宏開(kāi)始執(zhí)行時(shí)條件還沒(méi)有得到滿足而且這種對(duì)進(jìn)程狀態(tài)變量 state 延遲賦值也并沒(méi)有什么害處在某些特殊情況下這種思路方法還十分有益例如當(dāng)_wait_event 開(kāi)始執(zhí)行時(shí)條件為假但是在執(zhí)行到 16832行時(shí)就為真了這種變化只有在為有關(guān)進(jìn)程狀態(tài)代碼計(jì)算condition 變量值時(shí)才會(huì)出現(xiàn)問(wèn)題但是在代碼中這種情況我沒(méi)有發(fā)現(xiàn)16834:schedule(26686 行在第7章中討論)將C
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五版金融理財(cái)產(chǎn)品銷(xiāo)售合同細(xì)則4篇
- 二零二五年度農(nóng)業(yè)科技創(chuàng)新合作合同4篇
- 二零二五年度醫(yī)院院長(zhǎng)任期公共衛(wèi)生服務(wù)合同4篇
- 二零二五年度時(shí)尚服飾連鎖加盟合同協(xié)議3篇
- 二零二五年度公積金提取與個(gè)人住房貸款一體化合同
- 二零二五年度新能源發(fā)電項(xiàng)目并網(wǎng)接入合同4篇
- 2025年環(huán)境監(jiān)測(cè)技術(shù)的創(chuàng)新與應(yīng)用
- 二零二五年度寧德監(jiān)獄行政區(qū)生態(tài)園林景觀養(yǎng)護(hù)協(xié)議4篇
- 2025年度個(gè)人租車(chē)車(chē)輛故障應(yīng)急處理合同4篇
- 二零二五年度高端論壇組織策劃合同協(xié)議書(shū)4篇
- 河南省濮陽(yáng)市2024-2025學(xué)年高一上學(xué)期1月期末考試語(yǔ)文試題(含答案)
- 割接方案的要點(diǎn)、難點(diǎn)及采取的相應(yīng)措施
- 2025年副護(hù)士長(zhǎng)競(jìng)聘演講稿(3篇)
- 2024年08月北京中信銀行北京分行社會(huì)招考(826)筆試歷年參考題庫(kù)附帶答案詳解
- 原發(fā)性腎病綜合征護(hù)理
- (一模)株洲市2025屆高三教學(xué)質(zhì)量統(tǒng)一檢測(cè) 英語(yǔ)試卷
- 蘇教版二年級(jí)數(shù)學(xué)下冊(cè)全冊(cè)教學(xué)設(shè)計(jì)
- 金字塔原理與結(jié)構(gòu)化思維考核試題及答案
- 基礎(chǔ)護(hù)理學(xué)導(dǎo)尿操作
- DB11∕T 1028-2021 民用建筑節(jié)能門(mén)窗工程技術(shù)標(biāo)準(zhǔn)
- 四川省成都市溫江區(qū)2023-2024學(xué)年四年級(jí)下學(xué)期期末語(yǔ)文試卷
評(píng)論
0/150
提交評(píng)論