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