linux內(nèi)核完全注釋0.修正版_第1頁
linux內(nèi)核完全注釋0.修正版_第2頁
linux內(nèi)核完全注釋0.修正版_第3頁
linux內(nèi)核完全注釋0.修正版_第4頁
linux內(nèi)核完全注釋0.修正版_第5頁
已閱讀5頁,還剩701頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

本書對Linux早期操作系統(tǒng)內(nèi)核(v0.11)全部代碼文件進行了詳細全面的注釋和說明,旨在使讀者能夠在盡量短的時間LINUX工作原理的精髓,通過閱讀其源代碼能快速地完全理解內(nèi)核的運作的重要區(qū)別和改進方面,給出了選擇0.11(0.95)版作為研究的對象的原因。另外介紹了內(nèi)核源代碼的組織結(jié)構(gòu)及相互關(guān)系,版本的主要區(qū)別等部分。最后一章內(nèi)容總結(jié)性地介紹了繼續(xù)研究Linux系統(tǒng)的方法和著手點。作者保留本籍的修改和正式的所利.讀者可以自由本書全部和部分章節(jié)的內(nèi)容,但需要注明出處.由于目前本書尚為草稿階段,因此存在許多錯誤和不足之處,希望讀者能踴躍給予批評指正或建議.(息:gohigh@sh163net,或直接來信至:同濟大學(xué)機械電子工 (?2002,2003,2004byZhao?2002,2003,2004趙炯“RTFSC–ReadTheF**kingSourceCode–LinusBenedict序 EXT2文件系統(tǒng)與MINIX文件系 第1章概 第2章LINUX內(nèi)核體系結(jié) 第3章引導(dǎo)啟動程序 第4章初始化程序 第5章內(nèi)核代碼

第6章塊設(shè)備驅(qū)動程序(BLOCK 第7章字符設(shè)備驅(qū)動程序(CHAR 第8章數(shù)學(xué)協(xié)處理器 第9章文件系統(tǒng) 第10章內(nèi)存管理 第11章頭文件

第12章庫文件 第13章建造工具 第14章實驗環(huán)境設(shè)置與使用方 附 附錄1內(nèi)核主要常 附錄2內(nèi)核數(shù)據(jù)結(jié) 索 Linux內(nèi)核源代碼進行解剖,以linux內(nèi)核有一個完整而深刻的理解,對linux操作系統(tǒng)的基本工作原理真正理解和。Linux系統(tǒng)的一般使用方法或具有一定的編程基礎(chǔ),但比較缺乏閱讀目前內(nèi)核源代碼的基礎(chǔ)知識,又急切希望能夠進一步理解UNIX類操作系統(tǒng)內(nèi)核工作原理和實際代碼實現(xiàn)的者。這部分讀者的水平應(yīng)該界于初級與中級水平之間。目前,這部分讀者人數(shù)在Linux愛好者中所占的比例是很高的,而面向這部分讀者以比較易懂和有效的講解內(nèi)核的書籍資料不多。穩(wěn)定版等)Linux內(nèi)核整個源代碼的大小已經(jīng)非常得大(2.2.20268萬行代碼!被忽略。因此并不能給予讀者對實際Linux內(nèi)核有清晰而完整的理解。Linux內(nèi)核文件的工具程序、各個make文件的作用等均沒有涉及。因此對于處于初中級水平之間的讀者來說閱讀該書有些。浙江大學(xué)的《Linux內(nèi)核源代碼情景分析》一書,也基本有這些不足之處。甚至對于一些具有Linux系統(tǒng)應(yīng)用水平的計算機本科高年級學(xué)生,由于該書篇幅問題以及僅僅選擇性地講解內(nèi)核源代都會出現(xiàn)這個問題。該書剛面市時,本人曾極力勸說學(xué)生購之閱讀,并在二個月后閱讀學(xué)習(xí)情況,JohnLionsUNIXUNIX類操作系統(tǒng)內(nèi)核源代碼很UNIXV6版,其中系統(tǒng)調(diào)用等部分代碼是用早已過時的PDP-11系列機的匯編語言編制的,因此在閱讀與硬件部分相關(guān)的源代碼時就會遇到較大的。A.S.Tanenbaum的書《操作系統(tǒng):設(shè)計與實現(xiàn)》是一本有關(guān)操作系統(tǒng)內(nèi)核實現(xiàn)很好的書籍,但學(xué)習(xí)該書之后,并不能很順利地即刻著手進一步學(xué)習(xí)較新的Linux內(nèi)核源代碼實現(xiàn)。Linux內(nèi)核系統(tǒng)具體實現(xiàn)LinuxLinux系統(tǒng)的人在使用那些書學(xué)習(xí)內(nèi)核原理時,內(nèi)核的整體運作結(jié)構(gòu)并不能清晰地在腦海中形成。這在本人多年的Linux內(nèi)核學(xué)習(xí)過程中也深199110月份,LinuxLinusToravldsLinux0.03版后寫的一篇文章中也提到了同樣的問題。在這篇題為“LINUX--aunix-386kernelLinux是為了那些操作系統(tǒng)者和計算機科學(xué)系的學(xué)生使用、學(xué)習(xí)和。...自由軟件的GNUHurd系統(tǒng)如果開發(fā)出來就已經(jīng)顯得太龐大而不適合學(xué)習(xí)和理解?!盠inuxGNUHurd系統(tǒng)更為Linux內(nèi)核Linux內(nèi)核有一個完整而深刻的理解,對Linux操作系統(tǒng)的基本工作原理真正理解和。目前,已經(jīng)出現(xiàn)不少基于Linux早期內(nèi)核而開發(fā)的專門用于嵌入式系統(tǒng)的內(nèi)核版本,如DJJ的x86操作系統(tǒng)、Uclinux等(在 上有專門),世界上也有許多人認識到通過早期Linux內(nèi)核早期內(nèi)核版本的源代碼,的確是學(xué)習(xí)Linux系統(tǒng)的一種行之有效的途徑,并且對研究和應(yīng)用Linux嵌入.計算機(SIC)系統(tǒng)來說明所有系統(tǒng)程序的設(shè)計原理,從而既避免了實際計算機系統(tǒng)的復(fù)雜性,又能Linux早期內(nèi)核版本不包含對虛擬文VFSa.out執(zhí)行文件和對其它一些現(xiàn)有內(nèi)核中復(fù)雜子系統(tǒng)的說明。但由于本書是作為Linux內(nèi)核工作機理實現(xiàn)的,因此這也正是選擇早期內(nèi)核版本的優(yōu)點正如Linux系統(tǒng)的創(chuàng)始人在一篇組投稿上所說的,要理解一個軟件系統(tǒng)的真正運行機制,一定不重要的細節(jié)存在,但是若忽略這些細節(jié),就會對整個系統(tǒng)的理解帶來,并且不能真正了解一個實際系統(tǒng)的實現(xiàn)方法和。法耗費大量的時間和篇幅而完全忽略I/O,其實,前者通常不足一頁代碼,而后者往往要占到整個系統(tǒng)那么,如何選擇既能達到上述要求,又不被太多的內(nèi)容而頭腦,選擇一個適合的Linux內(nèi)核版核基本功能較為相近,又非常短小的0.11版內(nèi)核作為學(xué)習(xí)的最佳版本。下圖是對一些主要Linux內(nèi)Linux內(nèi)核源代碼量都在幾百萬行的數(shù)量上,極其龐大,對這些版本進行完全注釋和說明幾文件系統(tǒng)VFS、ext2或ext3文件系統(tǒng)、網(wǎng)絡(luò)子系統(tǒng)、新的復(fù)雜的內(nèi)存管理機制等。理器結(jié)構(gòu)和編程的知識或資料。例如可以從網(wǎng)上的80x86編程手冊(IN80386Programmer'sManual其三還應(yīng)具備初級使用Linux系統(tǒng)的簡單技能。LinusLinuxMINIXLinux內(nèi)核版本完全MINIX1.0文件系統(tǒng)。因此,在閱讀本書時,A.S.Tanenbaum的書《操作系統(tǒng):設(shè)計與實現(xiàn)》也已經(jīng)過時的(Linuxisobsolete)Linux內(nèi)Linux操作系統(tǒng)上默認的標準文件系統(tǒng)。但是,作為對Linux操作系統(tǒng)完整工作原理學(xué)習(xí)所使用的部分,原則上是越精簡越好。為了達到對一個操作系Linux0.11MINIX1.0文件系統(tǒng),對于理解一個操作系統(tǒng)中文件系統(tǒng)的實際組成和工作原理已經(jīng)足夠。這也是選擇Linux早期內(nèi)核版本進行學(xué)習(xí)的主要原因之一。此時,您應(yīng)該有十分的把握去進一步學(xué)習(xí)Linux內(nèi)核中各部分的工作原理和過程了。第1LinuxLinuxLinux內(nèi)核版本進行學(xué)習(xí)的優(yōu)點和不LinuxUNIX1991105日(這是第一次正式向外公布的時間。此后借助于Internet網(wǎng)絡(luò),經(jīng)過全世界各地計算機者的共同努力,現(xiàn)已成為當今世界上使用最多的一種UNIX類操作系統(tǒng),并且使用人數(shù)還在迅猛增長。Linux操作系統(tǒng)的誕生、發(fā)展和成長過程依賴于以下五個重要支柱:UNIX操作系統(tǒng)、MINIX操作0.01hacker1.0版本這段時間的發(fā)展經(jīng)過,也即對Linux的早期發(fā)展歷史進行詳細介紹。Linux操作系統(tǒng)是UNIX操作系統(tǒng)的一個克隆版本。UNIX操作系統(tǒng)是貝爾KenThompsonPDP-7計算機上運行他非常喜歡的星際旅行(Spacetravel)游BCPL語言(基本組合編程語言DennisRitchie1972C語言進行了改寫,使得UNIX系統(tǒng)在大專院校得到了推廣。了100多篇文章,5本計算機書籍。AST雖出生在紐約,但卻是荷蘭僑民(1914年他的祖輩來到)。他在紐約上的中學(xué)、M.I.T上的大學(xué)、加洲大學(xué)Berkeley分校念的博士。由于讀博士后的緣故,他來到了家鄉(xiāng)荷蘭。從此就與家鄉(xiāng)一直有來往。后來就在Vrije大學(xué)開始教書、帶。荷蘭首都Amsterdam是個常年陰雨綿綿的MINIX198719911.5。目前主要LinuxLinusLinux的發(fā)展很大原因是由于MINIXMINIX一直守護著的。GNU計劃和自由軟件FSF(theSoftwareFoundation)是由RichardM.Stallman于1984年一UNIX并且是自由軟件的完整操作系統(tǒng):GNU系統(tǒng)(GNU是"GNU'sNotNEW"用。雖然這些系統(tǒng)通常被稱作"Linux"StallmanGNU/Linux系90年代初,GNUemacs編輯系統(tǒng)、bashs程序、gcc系列編譯程序、gdbLinux操作系統(tǒng)的開發(fā)創(chuàng)造了一個合適的環(huán)境。這是Linux能夠誕生的基礎(chǔ)之一,以至于目前許多人都將Linux操作系統(tǒng)稱為POSIX(PortableOperatingSystemInterfaceforComputingSystems)IEEEISO/IEC開發(fā)的一UNIX實踐和經(jīng)驗,描述了操作系統(tǒng)的調(diào)用服務(wù)接口。用于保證編制的應(yīng)用程序可以在源代碼一級上在多種操作系統(tǒng)上移植和運行。它是在1980年早期一個UNIX用戶組CSRG的BSD操作系統(tǒng)的調(diào)用接口之間的區(qū)別重新調(diào)和集成。并于1984年定制出了/usr/group標準。1985年,IEEE操作系統(tǒng)技術(shù)標準小組(TCOS-SS)開始在ANSI的支持下責成IEEE標準制定有關(guān)程序源代碼可移植性操作系統(tǒng)服務(wù)接口正式標準。到了1986年4月,IEEE制定出19889月份批準的(IEEE1003.1-1988),也既以后經(jīng)常提到的POSIX.1標準。9945-1:1990標準。(API,IEEEPOSIX的工作就開始展開了。剛開始有十個批準的計(POSIX.3UNIXLinuxLinux能夠在標準的指導(dǎo)下進UNIXLinux內(nèi)核源代碼中(0.01版、0.11版)就了他正在著手一個操作系統(tǒng)的開發(fā),并且在開發(fā)之初已經(jīng)想到要實現(xiàn)與POSIX相兼容的問題了。在1981年,IBM公司推出了享譽全球的微型計算機IBMPC。在1981-1991,MS-DOS操作系當時Apple的MACs操作系統(tǒng)可以說是性能最好的,但是其天價使得沒人能夠輕易靠近。而能在大學(xué)中用于教學(xué)的UNIX源代碼也一直被地守衛(wèi)著不許公開。對于廣大的PC用戶,軟正在此時,出現(xiàn)了MINIX操作系統(tǒng),并且有一本描述其設(shè)計實現(xiàn)原理的書同時。由于AST的這本書寫的非常詳細,并且敘述得有條有理,于是幾乎全世界的計算機者都開始看這本書,以期能理解操作系統(tǒng)的工作原理。其中也包括Linux系統(tǒng)的創(chuàng)始者LinusBenedictTorvalds。當時(1991年),LinusBenedictTorvalds是赫爾辛基大學(xué)計算機科學(xué)系的二年級學(xué)生,也是一個在同一,GNU計劃已經(jīng)開發(fā)出了許多工具軟件。其中最受期盼的GNUC編譯器已經(jīng)出現(xiàn),但能得到源代碼。雖然GNU的操作系統(tǒng)HURD一直在開發(fā)之中,但在當時看來不能在幾年內(nèi)完成。為了能更好地學(xué)習(xí)計算機知識(或許也只是為了?,Linus使用圣誕節(jié)的壓歲錢和了一臺386兼容電腦,并從郵購了一套MINIX系統(tǒng)軟件。就在等待MINIX軟件期間,Linus認真學(xué)習(xí)了有關(guān)In80386的硬件知識。為了能通過Modem撥號連接到學(xué)校的主機上,他使用匯編語言并利用80386CPU的多任務(wù)特性編制出一個終端仿真程序。此后為了將自己一臺老式電腦上的軟件到新MINIX系統(tǒng)的諸多限制(MINIX雖然很好,但只是一個用GNU計正在開發(fā)中。但Linus已經(jīng)等不急了。習(xí)MINIX系統(tǒng)階段發(fā)展到開發(fā)自己的Linux系統(tǒng)的過程。doesn'toptimize”,gccMINIX-386系統(tǒng)上運行優(yōu)化的問題(MINIX-386Bruce這個想法逐步演變成想重新設(shè)計一個基于In80386體系結(jié)構(gòu)的新操作系統(tǒng)的構(gòu)思。(“RTFSC(19914月份開始,LinusMINIX-386系統(tǒng)(Hackingthekernel),并且GNU的軟件到該系統(tǒng)上(GNUgcc、bash、gdb等)413comp.os.minix上發(fā)布說自己已經(jīng)成功地將bashMINIX上,而且已經(jīng)愛不釋手、不能離開這個s軟件了。Linux199173comp.os.minix上發(fā)布的(當然,那時還不存在LinuxLinusFREAX?,F(xiàn)REAX的英文含義是怪誕的、怪物、在Linus另一個發(fā)布的消息中(1991825日comp.os.minix),他向所有MINIX用戶詢問“Whatwouldyouliketoseeinminix?”(MINIX系統(tǒng)中見到什么?”),在該消息中他首次透露出正在版)和gcc(1.40版)移植到了新系統(tǒng)上,而且在過幾個月就可以實用了。最后,LinusMINIX386的任務(wù)切Linus當時并沒有考慮。但是目前Linux幾乎可以運行在任何一種硬件體系結(jié)構(gòu)上。到了1991年的10月5日,Linus在comp.os.minix組上發(fā)布消息,正式向外宣布Linux內(nèi)核系統(tǒng)的誕生(minix-likekernelsourcesfor386-AT。這段消息可以稱為Linux的誕生,并且一直廣這個日子。所以RedHat公司選擇這個日子發(fā)布它的新系統(tǒng)也不是偶然的。Linux0.130.95版,Linus1.0版還很遙遠。同0.95版開始,對內(nèi)核的許多改進之處(補丁程序的提供)Linus的主要任務(wù)現(xiàn)在為止,版見表1–2所示。源代碼大小(gz壓縮后很不喜歡這個名稱。他認為既然是LinusLinux作為該操作系統(tǒng)的吧,于是Linux這個名稱就開始流傳下來。在Linus的自傳《JustforFun》一書中,Linus解釋說Linux這個名稱發(fā)布這個操作系統(tǒng),因為這個名字有些太自負了。而我為最終發(fā)布版準備的是什么名字呢?FreaxMakefile用于描-文件中就已經(jīng)包含有“Freax”這個名字了,大約存在了半年左右。但其實這可以光明正大地說我并不自負,或者部分坦白地說我并沒有本位。但好吧,這也是個好名從Linux早期源代碼中可以看出,LinuxLinus本人以外,最著名的人HackingonLinux。后來他開始作、銷售和研究者開放團體IETF成員。LinuxLinux操作系統(tǒng)剛問世時,他就懷著極大的熱linuxMaillistLinuxLinux做出貢獻。他11.又推出了ext3文件系統(tǒng)。該系統(tǒng)大大提高了文件系統(tǒng)的穩(wěn)定性和效率。作為對他的推崇,第97期1LinusTorvalds《Justforfun84-88Linux社區(qū)中另一位著名人物是AlanCox。他原工作于英國威爾士斯旺西大學(xué)(SwanseaUniversityCollege)MUD(Multi-UserDungeonorDimension,多用戶網(wǎng)絡(luò)游戲。在90年代早期games.mud組的posts中你可以找到他的大量帖子。他甚至為此還寫了一篇MUD的發(fā)展史(rec.games.mud組,1992年3月9日,AhistoryofMUD)。MUD游戲與網(wǎng)絡(luò)密切相關(guān),慢慢地他開始對計算機網(wǎng)絡(luò)著迷起來。為了玩游戲并提高電腦運386SX386BSDIn386SXCPU的電腦是不帶系統(tǒng)產(chǎn)生了,尤其是有關(guān)網(wǎng)絡(luò)方面的實現(xiàn)。在關(guān)于Linux單用戶運行模式問題的討論中,他甚至贊嘆Linux實現(xiàn)得巧妙(beautifully)。Linux0.95Linux系統(tǒng)編寫補丁程序(修改程序記得他最早的兩個補丁程Linus采納LinuxTCP/IP網(wǎng)絡(luò)代碼的最早使用人之一。后來他逐漸加入了Linux的開發(fā)隊伍,并成為Linux內(nèi)核源代碼的主要之一,也可以說成為Linux社團中繼他負責Linux內(nèi)核2.4.x的代碼。而Linus主要負責開發(fā)開發(fā)版內(nèi)核的研制(奇數(shù)版,比如2.5.x《內(nèi)核手冊》(TheLinuxKernelHackers'Guide)一書的作者MichaelK.Johnson也是最早接觸Linux操作系統(tǒng)的人之一(從0.97版)。他還是著名Linux文檔計劃(LinuxProject-LDP)的發(fā)起者之一。曾經(jīng)在LinuxJournel工作,現(xiàn)在RedHat公司工作。Linux系統(tǒng)并不是僅有這些中堅力量就能發(fā)展成今天這個樣子的,還有許多計算機高手對Linux做其中以字母順序列出了對Linux做出較大貢獻的近400人的列表,包括他們的地址和通信地UNIX操作系統(tǒng)--UNIX于1969年誕生在Bell。Linux就是UNIX的一種克隆系統(tǒng)。UNIXMINIX--MINIXUNIX1987年由著名計算機教授AndrewS.TanenbaumMINIX系統(tǒng)的出現(xiàn)并且提供源代碼(只能免費用于大學(xué)內(nèi))在全世界的大學(xué)中刮起了學(xué)習(xí)UNIX系統(tǒng)旋風(fēng)。Linux剛開始就是參照MINIX1991年才開始開發(fā)。GNU計劃--LinuxLinuxGNU計劃。Linux只是操作系統(tǒng)的一個內(nèi)核,沒有GNU軟件環(huán)境(比如說bashs),則Linux將寸步難行。POSIX標準--該標準在推動Linux操作系統(tǒng)以后朝著正規(guī)發(fā)展起著重要的作用。是Linux前只能發(fā)展到0.13(0.95)版的水平。-具 1200kBlinux-0.11.tar.Z-內(nèi)核源代碼文件。大小為94KB,展開后也僅有325KB; -BruceEvans'二進制執(zhí)行文件。是16位的匯編程序和裝入程序; -更新過的安裝信息文件。Linux0.11rootimage-0.110.11上。linux-0.11內(nèi)核中的所有源代碼程序,對每個源程序文件都進行了詳細注釋,包CGNUC語言的內(nèi)嵌匯編語言進行較為詳細的介并列出使用令和方法。這樣做有助于加深對代碼的理解,又能更好的了解所用硬件的使用方法,作188兆字節(jié),即使你花一生的經(jīng)歷來閱讀也未必能全部都看完。也許你要問“既然要從簡Linux0.01240K0.01核映像文件(bootimage),可以用來進行引導(dǎo)演示。如果再配上簡單的根文件系統(tǒng)映像文件(rootimage),拿Linux0.11版進行學(xué)習(xí)也有不足之處。比如該內(nèi)核版本中尚不包括有關(guān)專門的進程等待隊列、LinuxLinux工作Linux內(nèi)核中所有的代碼都進行了說明。為了保持結(jié)構(gòu)的完整性,對代碼的說明是以內(nèi)核中源代碼的組成結(jié)構(gòu)來進行的,基本上是以每個源代碼中的為一章內(nèi)容進行介紹。介紹的源程序文件的次序可參見前面的文件列表索引。整個Linux內(nèi)核源代碼的結(jié)構(gòu)如下列表1.1所示。所有結(jié)構(gòu)均是以linux為當前。1-1名 大 最后修改日期 說boot/ 2887bytes1991-12-062Linux操作系統(tǒng)的體系結(jié)構(gòu)、內(nèi)核源代碼文件放置的組織結(jié)構(gòu)以及每個文件大致功能。還介紹了Linux對物理內(nèi)存的使用分配方式、內(nèi)核的幾種堆棧及其使用方式和虛擬線性地址的使用分配。最后開始注釋內(nèi)核程序包中Linux/下的所看到的第一個文件,也即內(nèi)核代碼的總體Makefilemake使用。3boot/bootsect.sBIOS中參setup.s32head.s。這三個匯編程序完成了把內(nèi)核從塊設(shè)備上引導(dǎo)4init/main.c。它是內(nèi)核完成所有初始化工作并進入正程序時,你應(yīng)該已經(jīng)對Linux內(nèi)核有了一定的了解,可以說已經(jīng)有一半了?,但你還需要對文件系/6kernel/dev_blk/中的塊設(shè)備程序進行了注釋說明。該章主要含有硬盤、軟盤等塊設(shè)備7kernel/dev_chr/中的字符設(shè)備驅(qū)動程序進行注釋說明。這一章中主要涉及串行線路驅(qū)8kernel/math/中的數(shù)學(xué)協(xié)處理器的仿真程序。由于本書所注釋的內(nèi)核版本,還沒有真第9章介紹內(nèi)核源代碼fs/中的文件系統(tǒng)程序,在看這章內(nèi)容時建議你能夠暫停一下而去閱讀系統(tǒng)是只支持MINIX一種文件系統(tǒng),Linux0.11版也不例外。10mm/In80X86微處理行方式的說明,這些知識基本上都可以參考In80386程序員編程手冊(In80386Programmer'sReferenceManual)。但在此章中,以源代碼中的運用實例為對象進行解說,應(yīng)該可以更好地理解它的工Linux內(nèi)核分析書籍都缺乏對內(nèi)核頭文件的描述,因此對于一個初學(xué)者來講,在閱讀內(nèi)核程序時會碰到許多。本書的第11章對include/中的所有頭文件進行了詳細說明,基本上對每一個12Linux0.11lib/中的所有文件。這些庫函數(shù)文件主要向編譯系統(tǒng)等并不是很多,可以很快地看完。這也是我們?yōu)槭裁催x擇0.11版的原因之一。第13章介紹tools/ 它僅用于將內(nèi)核中的磁盤引導(dǎo)程序塊與其它主要內(nèi)核模塊連接成一個完整的內(nèi)核映像(kernelimage)文LinuxLinux0.11源代碼的語法使其能在RedHat9系統(tǒng)下順利編譯出正確的內(nèi)核來。Linux內(nèi)核中的一些常數(shù)定義和基本數(shù)據(jù)結(jié)構(gòu)定義,以及保護模PC機硬件方面的信息。在參考繁雜凌亂的文獻列表。比如在Linux文檔項目LDP(LinuxProject)中的文件時,我們會明確地列出具體需要參考哪一篇HOWTO文章,而并不是僅僅給出LDP的地址了事。LinusLinux3MJBach著的《UNIX操作法,Linux內(nèi)核源代碼中很多重要函數(shù)的名稱都取自該書。因此,在閱讀本書時,這是一本必不可少的1版。LinusMINIX1.0Linux內(nèi)核全可以從Tanenbaum的書中獲得。LinuxLinuxGURU的初步知識。這時你應(yīng)該去閱讀更多的源代碼,最好是循序漸進地從1.0版本開始直到的正在開發(fā)中的奇數(shù)編號的版本。在撰寫這本書時的Linux內(nèi)核是2.5.44版。當你能快速理解這些開發(fā)中的版本甚至能提出自己的建議和補Linux誕生和發(fā)展不可缺少的五個支柱:UNIXLinux提供了POSIXLinux提供了實現(xiàn)與標準兼容系統(tǒng)的參考指南、A.S.TMINIXLinux的誕生起到了不可忽缺的參考、Internet是Linux成長和壯大的必要環(huán)境。最后本章概述了基本內(nèi)第2LinuxLinuxLinux內(nèi)核源代碼中組織形式以及子中各個代碼文件的主要功能以及基本調(diào)用的層次關(guān)系。接下來就直接切入正題,從Linux/Makefile開始,對每一行代碼進行詳細注釋說明。本章內(nèi)容可以X窗口系統(tǒng)、s命令解釋系統(tǒng)以及那些內(nèi)核編程接口等系統(tǒng)程序;操作系統(tǒng)內(nèi)核程序即是本書所感的部分,它主要用于對硬件資源的抽象和調(diào)度。Linux內(nèi)核的主要用途就是為了與計算機硬件進行交互,實現(xiàn)對硬件部件的編程控制和接口操作,Linux0.11Linux內(nèi)核的基本體系結(jié)構(gòu)、主Linux0.11內(nèi)核編譯Linux0.11內(nèi)核,則是采用了單內(nèi)核模式。單內(nèi)核模式的主要優(yōu)點是內(nèi)核代碼結(jié)構(gòu)緊湊、執(zhí)行速在單內(nèi)核模式的系統(tǒng)中,操作系統(tǒng)所提供服務(wù)的流程為:應(yīng)用主程序使用指定的參數(shù)值執(zhí)行系統(tǒng)調(diào)t使Ur到lModel體的參數(shù)值調(diào)用特定的系統(tǒng)調(diào)用服務(wù)程序,而這些服務(wù)程序則根據(jù)需要再底層的一些支持函數(shù)以完成特定的功能。在完成了應(yīng)用程序所要求的服務(wù)后,操作系統(tǒng)又從態(tài)切換回用戶態(tài),返回到應(yīng)用程序中繼Linux5個模塊構(gòu)成,它們分別是:進程調(diào)度模塊、內(nèi)存管理模塊、文件系統(tǒng)模塊、進CPU,同時保證內(nèi)核地執(zhí)行硬件操作。內(nèi)存管理模塊用于確保所有進程能夠安全地共享機器主內(nèi)存區(qū),同時,內(nèi)存管理模塊還支持虛擬內(nèi)存管理方式,使得Linux支持進程使用比實際內(nèi)存空間的換回來。文件系統(tǒng)模塊用于支持對外部設(shè)備的驅(qū)動和。虛擬文件系統(tǒng)模塊通過向所有的外部設(shè)2-3所示。其中的連線代表它們之間的依賴關(guān)系,虛線和虛框部分Linux0.11中還未實現(xiàn)的部分(Linux0.95版才開始逐步實現(xiàn)虛擬文件系統(tǒng),而網(wǎng)絡(luò)接口的支持到0.96版才有。(NFS成圖2-4所示的框圖結(jié)構(gòu)。 硬件控函數(shù) ,共可管理15級中斷向量。其級連示意圖見圖2-5所示。其中從的INT引腳連接到主的IR2引腳上。主8259A的端口址是0x20,從是0xA0。時鐘時鐘鍵盤聯(lián)int2IRQ5軟盤IRQ6并行口1IRQ7IR3IR4數(shù)據(jù)D7-實時鐘IRQ8 保留 協(xié)處理器IRQ13硬盤IRQ14 IR0CAS2-IR3IR4指令對8259A進行初始化編程的狀態(tài)。一旦完成了初始化編程,即進入操作狀態(tài),此時即IRQ15對于Linux內(nèi)核來說,中斷信號通常分為兩類:硬件中斷和軟件中斷(異常)。每個中斷是由0-255用,屬于軟件中斷,但In公司稱之為異常。因為這些中斷是在CPU執(zhí)行指令時探測到異常情況而引(在Linux系統(tǒng)中,則將int32--int47(0x20--0x2f)對應(yīng)于8259A中斷控制發(fā)出的硬件中斷請求信號IRQ0-IRQ15,并把程序編程發(fā)出的系統(tǒng)調(diào)用(system_call)中斷設(shè)置為int128(0x80)。(tier_interrupt以來經(jīng)過的時鐘滴答數(shù)。每當發(fā)生一次時鐘中斷該值就增CPLdo_timer()1。如果此時當前進程時間程序是一個可執(zhí)行的文件,而進程(process)是一個執(zhí)行中的程序?qū)嵗@梅謺r技術(shù),在Linux的時間片很短(例如15個系統(tǒng)滴答=150毫秒process則稱為父進程(parentprocess。內(nèi)核程序使用進程標識號(processID,pid)來標識每個進程。進程由Linux系統(tǒng)中,一個進程可以在內(nèi)核態(tài)(kernelmode)或用戶態(tài)(usermode)下執(zhí)行,因此,LinuxLinux系統(tǒng)中,進程表項task_structinclude/linux/sched.h中。有些書上稱其為PCB(ProcessControlBlock)PD(ProcessorDescriptor。其中保存著用于控structtask_structlong long longpriority longsignal //信號。是位圖,每個比特位代表一種信號,信號值=位偏移值+1。structsigactionsigaction[32]//信號執(zhí)行屬性結(jié)構(gòu),對應(yīng)信號將要執(zhí)行的操作和標志信息。longblocked //進程碼(對應(yīng)信號位圖)。int unsignedlong unsignedlong unsignedlong (字節(jié)數(shù))unsignedlong (字節(jié)數(shù))unsignedlong long long long long long unsignedshort unsignedshort unsignedshort unsignedshort unsignedshort unsignedshort long long long long long long unsignedshort int unsignedshortumask //文件創(chuàng)建屬性位。structm_inode*pwd //當前工作 i節(jié)點結(jié)構(gòu)。structm_inode*root //根 i節(jié)點結(jié)構(gòu)。structm_inode*executable//執(zhí)行文件i節(jié)點結(jié)構(gòu)。unsignedlongclose_on_exec//執(zhí)行時關(guān)閉文件句柄位圖標志。(參見 structfile*filp[NR_OPEN]//文件結(jié)構(gòu)指針表,最多32項。表項號即是文件描述符的值。structdesc_structldt[3]//任務(wù)局部描述符表。0-空,1-代碼段cs,2-數(shù)據(jù)和堆棧段ds&ss。structtss_structtss //進程的任務(wù)狀態(tài)段信息結(jié)構(gòu)。U文。當內(nèi)核需要切換(h)至另一個進程時,它就需要保存當前進程的所有狀態(tài),也即保存當前進nux2-6所示。進程狀態(tài)保存狀態(tài)。在Linux系統(tǒng)中,睡眠等待狀態(tài)被分為可中斷的和不可中斷的等待狀態(tài)。0系統(tǒng)調(diào)用或中 返10 204當進程正在被CPU(running醒而進入準備運行狀態(tài),該狀態(tài)稱為就緒態(tài)。這些狀態(tài)(圖間一列)在內(nèi)核中表示方法相同,都被成為處于TASK_RUNNING狀態(tài)。wake_up()函數(shù)明確喚醒時才能轉(zhuǎn)換到可SIGSTOP、SIGTSTP、SIGTTINSIGTTOU時就會進入暫停狀態(tài)??上蚱浒l(fā)送自愿地放棄CPU(TASK_UNINTERRUPTIBLE或ASK_INTERRUPTIBLE核數(shù)據(jù)錯誤,內(nèi)核在執(zhí)行臨界區(qū)代碼時會一切中斷。在boot/中引導(dǎo)程序把內(nèi)核從磁盤上加載到內(nèi)存中,并讓系統(tǒng)進入保護模式下運行后,就開始執(zhí)行系統(tǒng)初始化程序init/main.c。該程序首先確定如何分配使用系統(tǒng)物理內(nèi)存,然后調(diào)用內(nèi)核各部分的初0s00pause()系統(tǒng)調(diào)用,在對調(diào)度程序的初始化過程(sched_init())0的運行環(huán)境進行了設(shè)置。這包括人工預(yù)先exdh(TSS)描述符和局部描述符表(LDT)tr和局部描述符表寄存器ldtr中。00016MB0的代碼段和數(shù)據(jù)段分別包含在內(nèi)核代碼段和數(shù)據(jù)0運行著main.c程序。宏move_to_user_mode的功能就是把運行級從內(nèi)核態(tài)的0級變換到用戶態(tài)的3級,但是仍然繼續(xù)執(zhí)行原來的代碼指令流。在移動到任務(wù)0的過程中,宏move_to_user_mode使用了中斷返回指令造成級改變的方法。該0代碼段3上運行。參見圖2-7所示的級發(fā)生變化時中斷返回堆棧結(jié)構(gòu)示意圖。0SP0TSS0SP0TSSmove_to_user_mode0數(shù)據(jù)段選擇符和內(nèi)核堆棧指針。然后壓入標志0代碼段選擇符和執(zhí)行中斷返回后需要執(zhí)行的下一條指令的偏移位置。該偏移位置是iret后的一條指令處。iret指令時,CPUCS:EIPCPU棧指針彈出到SS:ESP中。由于級發(fā)上了變化,段寄存器DS、ES、FS和GS的值變得無效,此時(long)&init_task建任務(wù)1(進程1)之前保持“干凈”狀態(tài)。64fork()系統(tǒng)調(diào)用會因為任務(wù)數(shù)組表中沒有可用空項而出錯返回。然后(ASK_UNINTERRUPTIBE隨后對的任務(wù)數(shù)據(jù)結(jié)構(gòu)進行修改。把當前進程設(shè)置為新進程的父進程,清除信號位圖并復(fù)位新15個系統(tǒng)滴答數(shù)(150毫秒。接著根據(jù)當前進程設(shè)置任務(wù)tss.esp0tss.ss0被設(shè)器,把還需要把協(xié)處理器的完整狀態(tài)保存到新進程的tss.i387結(jié)構(gòu)中。此后系統(tǒng)設(shè)置新任務(wù)的代碼和數(shù)據(jù)段基址、限長并當前進程內(nèi)存分頁管理的頁表。如果父進程項,其中址信息指向新進程任務(wù)結(jié)構(gòu)中的tss和ldt。最后再將新任務(wù)設(shè)置成可運行狀態(tài)并返回新進由前面描述可知,LinuxTASK_RUNNING狀態(tài),只是暫時沒有被CPU運行。進程的搶占發(fā)生在進程處于用戶態(tài)執(zhí)行階段,在內(nèi)核態(tài)執(zhí)行時是不能被搶占的。一定的調(diào)度策略。在Linux0.11中采用了基于優(yōu)先級排隊的調(diào)度策略。TASK_RUNNING狀態(tài)進程的時間片都已經(jīng)用完,系統(tǒng)就會根據(jù)每個進程的優(yōu)先計算的是:countercounter2schdeule()TASK_RUNNING狀態(tài),重復(fù)上述過程,直到選擇出一個進程為止。最后調(diào)用switch_to()執(zhí)行實際的進程切換操作。執(zhí)行實際進程切換的任務(wù)由switch_to()宏定義的一段匯編代碼完成。在進行切換之前,switch_to()的寄存器信息恢復(fù)到CPU中,系統(tǒng)就正式開始運行新切換的任務(wù)了。這個過程可參見圖2-8所示。8038680386TSSCPU當一個用戶程序調(diào)用exit()系統(tǒng)調(diào)用時,就會執(zhí)行內(nèi)核函數(shù)do_exit()。該函數(shù)會首先釋放進程代碼段 的i節(jié)點進行同步操作。如果進程有子進程,則讓init進程作為其所有子進程的父進程。如果進程是一通常會終止該會話中的所有進程。然后把進程狀態(tài)置為僵死狀態(tài)TASK_ZOMBIE。并向其原父進程發(fā)送SIGCHLD信號,通知其某個子進程已經(jīng)終止。最后do_exit()調(diào)用調(diào)度函數(shù)去執(zhí)行其它進程。由此可wait()waitpid()函數(shù)等待其某個子進程終止。當?shù)却淖?640K顯存和BIOS其中,Linux內(nèi)核程序占據(jù)在物理內(nèi)存的開始部分,接下來是用于供硬盤或軟盤等塊設(shè)備使用的高速緩沖區(qū)部分。當一個進程需要塊設(shè)備中的數(shù)據(jù)時,系統(tǒng)會首先將數(shù)據(jù)讀到高速緩沖區(qū)中;當有數(shù)RAM虛擬盤的系統(tǒng),主內(nèi)存區(qū)頭統(tǒng)中的內(nèi)存進行有效的管理。在InCPU中,提供了兩種內(nèi)存管理(變換)系統(tǒng):內(nèi)存分段系統(tǒng)System在Linux0.113a.程序(進程)的邏輯地址;b.CPU的線性地址;c.邏輯地址(LogicalAddress)是指有程序產(chǎn)生的與段相關(guān)的偏移地址部分。在In保護模式下即是線性地址(LinearAddress)是邏輯地址到物理地址變換之間的中間層。程序代碼會產(chǎn)生邏輯地址,或者說是段中的偏移地址,加上相應(yīng)段的址就生成了一個線性地址。如果啟用了分頁機制,那么線80386的線性地址空間容量為4G。物理地址(PhysicalAddress)是現(xiàn)在CPU外部地址總線上的尋址物理內(nèi)存的地址信號,是地址 虛擬內(nèi)存(VirtualMemory)是指計算機呈現(xiàn)出要比實際擁有的內(nèi)存大得多的內(nèi)存量。因此它允許源的系統(tǒng)上實現(xiàn)。一個很恰當?shù)谋扔魇牵耗悴恍枰荛L的軌道就可以讓一列火車從開到。你只需要足夠長的鐵軌(比如說3公里)就可以完成這個任務(wù)。采取的方法是把后面的鐵軌立刻鋪到火車的理需要完成的任務(wù)。在Linux0.11內(nèi)核中,給每個程序(進程)都劃分了總?cè)萘繛?4MB的虛擬內(nèi)存空間。因此程序的邏輯地址范圍是0x 到0x 上。每次對內(nèi)存的都是對內(nèi)存段中內(nèi)存的。當一個程序一個內(nèi)存地址時,通過把相應(yīng)的段性地址就被送到CPU的外部地址總線上,用于直接尋址對應(yīng)的物理內(nèi)存。射到實際物理內(nèi)存地址上。與分段機制類似,分頁機制允許我們重新定向(變換)每次內(nèi)存,以適的法。通常虛擬內(nèi)存空間要比實際物理內(nèi)存量大得多。使用一塊不存在的內(nèi)存時(也即在內(nèi)存頁表項中已標出相應(yīng)內(nèi)存頁面不在內(nèi)存中,CPU就需要法來得知這個情況。這是通過80386的頁錯誤異常中斷來實現(xiàn)的。當一個進程一個不存在頁面中的CPUCR2控制寄存器中。(比如硬盤上)加載到物理內(nèi)存中。如果此時物理內(nèi)存已經(jīng)被全部占用,那么可以借助二級空間的InCPU使用段(Segment)的概念來對程序進行尋址。每個段定義了內(nèi)存中的某個區(qū)域以及GDTLDTLDTLDT映系統(tǒng)段sys任務(wù)任務(wù)任務(wù)任務(wù)任務(wù)圖中畫出了具有兩個任務(wù)時的情況。對于中斷描述符表idt,它是保存在內(nèi)核代碼段中的。由于在Linux0.11內(nèi)核中,內(nèi)核和各任務(wù)的代碼段和數(shù)據(jù)段都分別被映射到線性地址空間中相同基址處,且段限長也一樣,因此內(nèi)核和任務(wù)的代碼段和數(shù)據(jù)段都分別是的。另外,Linux0.11內(nèi)核中沒有使用系續(xù)地址空間。對于In80386系統(tǒng),其CPU可以提供多達4G的線性地址空間。對于Linux0.11內(nèi)核,GDT2562項空閑、2項系統(tǒng)使用,每個進程使02-11Linux0.11CPU整個線性地址空間中的地址,然后再使用頁表PDT(一級頁表)和頁表PT(二級頁表)映射到實際物理地址頁上。因此兩種變換不能。從Linux內(nèi)核0.99版以后,對內(nèi)存空間的使用方式發(fā)生了變化。每個進程可以單獨整個4G的開機初始化時bootsectROMBIOS0x7c00處時,并沒有設(shè)置堆棧段,當然程序也esp0xff000x9000:0xff00boot/bootsect.s61、62行。setup.s程序中也沿用了bootsect中設(shè)置的堆棧段。這就是系統(tǒng)初始化時臨時使用的堆棧。進入保護模式時(0x10,espuser_stack數(shù)組的頂端(head.s31行1頁內(nèi)存(4K)作為堆棧使用。user_stacksched.c67--721024個長字。它在物理內(nèi)存中的位置可參見下圖2-12所示。此時該堆棧是內(nèi)核程序自己使用的堆棧。內(nèi)存頁表(4kX表初始化時在main.c中,在執(zhí)行move_to_user_mode()代碼之前,系統(tǒng)一直使用上述堆棧。而在執(zhí)行過據(jù)結(jié)構(gòu))個字節(jié),大約為3K字節(jié)。而任務(wù)的用戶態(tài)堆棧卻可以在用戶的64MB空間內(nèi)延伸。每個任務(wù)(0)64MB地址空間。當一個任務(wù)(進程)剛被創(chuàng)建時,它的用戶態(tài)堆棧指針被設(shè)置在其地址空間的末端(64MB頂端),而其內(nèi)核態(tài)堆棧則被設(shè)置成位于其任務(wù)數(shù)據(jù)結(jié)構(gòu)分頁機制確定。由于Linux實現(xiàn)了寫時功能(CopyonWrite),因此在進程被創(chuàng)建后,若該進程及在建立新任務(wù)時,fork程序在任務(wù)tss段的內(nèi)核級堆棧字段(tss.esp0和tss.ss0中設(shè)置的,參見kernel/fork.c,93行:p->tss.esp0=PAGE_SIZE+(long)p;p->tss.ss0=0x10;p是新任務(wù)的任務(wù)數(shù)據(jù)結(jié)構(gòu)指針,tss堆棧指針進程指針tss.ss00x10呢?這要從內(nèi)核代碼段的長度范圍來說明。head.s16MB。這Linux0.98版后內(nèi)核段的限長被修改成了1GB。這兩個值構(gòu)成。在任務(wù)切換時,老任務(wù)的內(nèi)核棧指針(esp0)CPU來講,這兩個值是只讀結(jié)構(gòu)所在頁面的末端,而它的用戶態(tài)堆棧就是前面進入保護模式后所使用的堆棧,也即sched.c的開始并且限長為640KB的段。參見圖2-7所示。eflagsiret退出內(nèi)核程序返回到用戶程序時,將恢復(fù)用戶態(tài)的堆棧和eflags。這個過程見圖2-14所示。 Linux內(nèi)核是一種單內(nèi)核模式的系統(tǒng),因此,內(nèi)核中所有的程序幾乎都有緊密的聯(lián)系,它們之要在開始閱讀內(nèi)核源代碼之前,先熟悉一下源代碼文件的結(jié)構(gòu)和安排。這里我們首先列出Linux內(nèi)核完整的源代碼,包括其中的子。然后逐一介紹各個中所tarlinux-0.11.tar.gzlinux/中。其中的結(jié)構(gòu)見圖2-15所示:頭文件│├─│├─│└─│├─│├─│└─ 中含有14個子 ,總共包括102個代碼文件。下面逐個對這些子 中除了包括所有的14個 編譯。因此,make工具軟件是程序項目的管理軟件。 有的源代碼文件,只要在linux 下運行一次make軟件即可。 boot3301個扇區(qū)PCROMBIOSBIOS0x7C00處進行執(zhí)行。setup.s程序主要用于機器的硬件配置參數(shù),并把內(nèi)核模塊system移動到適當?shù)膬?nèi)存位置處。 MINIXMINIXLinux分區(qū)。雖然使用的是Linux則采用了多線程方式。由于采用了多線程處理方式,Linux程序就必須處理競爭條件的發(fā)生,Linux系統(tǒng)對資源分配進行了嚴格地檢查,并且在內(nèi)核模式下運行時,如果任務(wù)沒有主動睡眠(調(diào)用sleep(),就不讓內(nèi)核切換任務(wù)。fs/是文件系統(tǒng)實現(xiàn)程序的,共包含17個C語言程序。這些程序之間的主要關(guān)系見圖虛框中是的程序文件不屬于文件系統(tǒng),帶箭頭的線條表示關(guān)系,粗線條表示有相互關(guān)系。 blockfilechar圖2-16 中各程序中函數(shù)之間的關(guān)系由圖可以看出,該中的程序可以劃分成四個部分:高速緩沖區(qū)管理、低層文件操作、文件數(shù)據(jù)和文件函數(shù),在對本中文件進行注釋說明時,我們也將分成這四個部分來描述。對于文件系統(tǒng),我們可以將它看成是內(nèi)存高速緩沖區(qū)的擴展部分。所有對文件系統(tǒng)中數(shù)據(jù)的,都需要首先到高速緩沖區(qū)中。本中的程序主要用來管理高速緩沖區(qū)中緩沖塊的使用分配和塊設(shè)備上的文件系統(tǒng)。管理高速緩沖區(qū)的程序是buffer.c,而其它程序則主要都是用于文件系統(tǒng)管理。在file_table.c文件中,目前僅定義了一個文件句柄(描述符)結(jié)構(gòu)數(shù)組。ioctl.c文件將kernel/chr_drv/tty.c中的函數(shù),實現(xiàn)字符設(shè)備的io控制功能。exec.c程序主要包含一個執(zhí)行程序函數(shù)read_write.c程序用于實現(xiàn)文件讀/寫和定位三個系統(tǒng)調(diào)用函數(shù)。stat.c程序中實現(xiàn)了兩個獲取文件狀態(tài)的系統(tǒng)調(diào)用函數(shù)。open.c程序主要包含實現(xiàn)修改文件屬性和創(chuàng)建與關(guān)閉文件的系統(tǒng)調(diào)用函數(shù)。名和文件名的操作函數(shù)和系統(tǒng)調(diào)用函數(shù)。block_dev.c程序包含塊數(shù)據(jù)讀和寫函數(shù)。inode.c程序中包i節(jié)點操作的函數(shù)。truncate.c程序用于在刪除文件時釋放文件所占用的設(shè)備數(shù)據(jù)空間。bitmap.c程序用于處理文件系統(tǒng)中i節(jié)點和邏輯數(shù)據(jù)塊的位圖。super.c程序中包含對文件系統(tǒng)超級塊的處理函數(shù)。buffer.cll_rw_block是塊設(shè)備的底層讀fskernel/blk_drv/ll_rw_block.c中的塊設(shè)備讀寫驅(qū)動函數(shù)。放在這里只是讓 頭文件中總共有32個.h頭文件。其中主下有13個,asm子中有4個,linux子中10個,sys子中有5個。這些頭文件各自的功能見如下簡述,具體的作用和所包含的信息請參見 錯誤號頭文件。包含系統(tǒng)中各種出錯號。(Linus從minix中引進的) 個宏(va_start,va_arg和va_end用于vsprintf、vprintf、vfprintf函數(shù)。 ,, LinuxLIBRARY,則還包括系統(tǒng)調(diào)用號和內(nèi)嵌匯編_syscall0() <linux/config.h>內(nèi)核配置頭文件。定義鍵盤語言和硬盤類型(HD_TYPE) <linux/kernel.h>內(nèi)核頭文件。含有一些內(nèi)核常用函數(shù)的定義 該中僅包含一個文件main.c。用于執(zhí)行內(nèi)核所有的初始化工作,然后移到用戶模式創(chuàng)建新進程,并在控制臺設(shè)備上運行s程序。并設(shè)置了中斷允許標志。在執(zhí)行從態(tài)移到用戶態(tài)之后,系統(tǒng)第一次調(diào)用創(chuàng)建進程函數(shù)fork(),創(chuàng)建運行s程序。 linux/kernel12Makefile3個子。所有處理任kernel/fork、exit、調(diào)度程序以及一些系統(tǒng)調(diào)用程序等。還包括處get_hd_blocktty_write等。由于這些文件中代碼之間調(diào)用關(guān)系復(fù)雜,因此這里就不詳細列出各文件之間的關(guān)系圖,但仍然可以進行大概分類,見圖2-17所示。asm.s程序是用于處理系統(tǒng)硬件異常所引起的中斷,對各硬件異常的實際處理程序則是在traps.c文件中,在各個中斷處理過程中,將分別調(diào)用traps.c中相應(yīng)的C語言處理函數(shù)。fork.c程序給出了sys_fork系統(tǒng)調(diào)用中使用了兩個C語言函數(shù):find_empty_process(日的秒數(shù),作為開機秒時間。僅在init/main.c中被調(diào)用一次。printk.c程序包含一個內(nèi)核信息顯示函數(shù)printk()。signal.c程序中包括了有關(guān)信號處理的4個系統(tǒng)調(diào)用以及一個在對應(yīng)的中斷處理程序中處理信號的函do_signal()。system_call.sLinux系統(tǒng)調(diào)用(int0x80)的接口處理過程,實際的處理過程則包含在各系統(tǒng)調(diào)用相應(yīng)的C語言處理函數(shù)中,這些處理函數(shù)分布在整個Linux內(nèi)核代碼中。塊設(shè)備驅(qū)動程序子通常情況下,用戶是通過文件系統(tǒng)來設(shè)備的,因此設(shè)備驅(qū)動程序為文件系統(tǒng)實現(xiàn)了調(diào)用接口。之間使用了高速緩沖機制。在塊設(shè)備上的數(shù)據(jù)時,系統(tǒng)首先以數(shù)據(jù)塊的形式把塊設(shè)備上的數(shù)據(jù)讀入到高速緩沖區(qū)中,然后再提供給用戶。blk_drv子共包含4c1blk.h由于是塊設(shè)備程序的,所以與C文件放在一起。這幾個文件之間的大致關(guān)系,見圖2-18所示。圖2-18 blk.h3個C程序中共用的塊設(shè)備結(jié)構(gòu)和數(shù)據(jù)塊請求結(jié)構(gòu)。hd.c程序主要實現(xiàn)對硬盤數(shù)據(jù)塊進行讀/do_hdrequest()函數(shù);floppy.c程序中主要實現(xiàn)了對軟盤數(shù)據(jù)塊的讀寫驅(qū)動函數(shù),主要是do_fd_request函數(shù)。ll_rw_blk.c中程序?qū)崿F(xiàn)了低層塊設(shè)備數(shù)據(jù)讀寫函數(shù)塊設(shè)備數(shù)據(jù)的地方被調(diào)用,尤其是在高速緩沖區(qū)處理文件fs/buffer.c中。字符設(shè)備驅(qū)動程序子字符設(shè)備程序 共含有4個C語言程序和2個匯編程序文件。這些文件實現(xiàn)了對串行端 tty_io.cttytty_read()tty_write(),為文件系統(tǒng)提供了上層Cdo_tty_interrupt(),該函數(shù)將會在中斷類型為讀對顯示器和鍵盤中斷的初始化設(shè)置程序con_init()。會在實現(xiàn)系統(tǒng)調(diào)用sys_ioctl()的fs/ioctl.c程序中被調(diào)用。 該子Cmath_emulate.cmath_emulate()int7的中斷處理程序調(diào)用的C函數(shù)。當機器中沒有數(shù)學(xué)協(xié)處理器,而CPU卻又執(zhí)行了協(xié)處理器的指令時,就會該協(xié)處理器的仿真代碼。本程序中只是打印一條出錯信息,并向用戶程序發(fā)送一個協(xié)處理器錯誤信號 與普通靜態(tài)庫的實現(xiàn)方法完全一樣。讀者可從中了解一般libc函數(shù)庫的基本組成原理。在lib/中共12個Ctytsomalloc.c程序較長以外,其它的程序很短,有的只有一二這些文件中主要包括有退出函數(shù)_exit()、關(guān)閉文件函數(shù)close(fd)、文件描述符函數(shù)dup()、文件函數(shù)wait()、創(chuàng)建會話系統(tǒng)調(diào)用setsid()以及在include/string.h中實現(xiàn)的所有字符串操作函數(shù)。 該2個代碼文件。主要用于管理程序?qū)χ鲀?nèi)存區(qū)的使用,實現(xiàn)了進程邏輯地址到線性地址Linux3864G6464MB。所有內(nèi)核程序占用其中第一個段,并且物理地址與該段線性地址相同。然后每個貝,并執(zhí)行寫時機制。page.s文件包括內(nèi)存頁面異常中斷(int14)處理程序,主要用于處理程序由于缺頁而引起的頁異常memory.c程序包括對內(nèi)存進行初始化的函數(shù)mem_init(),由page.s的內(nèi)存處理中斷過程調(diào)用的do_no_page()和do_wp_page()函數(shù)。在創(chuàng)建新進程而執(zhí)行進程操作時,即使用該文件中的內(nèi)存處理 該下的build.cLinux各個中被分別編譯生成的目標代碼連接合并成一個可運行的內(nèi)核映象文件image。其具體的功能可參見下一章內(nèi)容。在Linux系統(tǒng)中,內(nèi)核為應(yīng)用程序提供了兩方面的接口。其一是系統(tǒng)調(diào)用接口(5章中說明int0x80;另一方面是通過內(nèi)核庫函數(shù)(12章中說明)與內(nèi)核進行信息交流。內(nèi)核庫函數(shù)是基本C函數(shù)庫libc的組成部分。許多系統(tǒng)調(diào)用是作為基本C語言函數(shù)庫的一部分實現(xiàn)的。用象libc等庫中的函數(shù)來內(nèi)核資源。通過調(diào)用這些庫中的程序,應(yīng)用程序代碼能夠完成各種常用工作,例如,打開和關(guān)閉對文件或設(shè)備的、進行科學(xué)計算、出錯處理以及組和用戶標識號ID等系統(tǒng)調(diào)用是內(nèi)核與外界接口的最。在內(nèi)核中,每個系統(tǒng)調(diào)用都有一個序列號(在的話,程序的移植性就不好了。因此目前LinuxLSB(LinuxStandardBase)和許多其它標準都不允許應(yīng)用程序直接系統(tǒng)調(diào)用宏。系統(tǒng)調(diào)用的有關(guān)文檔可參見Linux操作系統(tǒng)的手冊的第2部分。I/Ofopenfcloseopen和close類似的功能,但卻是在更高的層次上。在這種情況下,系統(tǒng)調(diào)用通常能提供比庫函數(shù)略微好一些的性能,但是庫函數(shù)卻能提供的功能,而且更具檢錯能力。系統(tǒng)提供的庫函數(shù)有關(guān)文檔可參見操作系統(tǒng)的手冊第3部分。從本節(jié)起,我們開始對內(nèi)核源代碼文件進行注釋。首先注釋linux Makefilemake運行時的輸入數(shù)據(jù)文件。只Makefile的當前中鍵入makeMakefile文件中的設(shè)置對源程序或目標代makeMakefile信息文件,該文件描述了整個程序包中各程序make命令就能進行所有必要的重新編譯工作。make程序Makefile數(shù)據(jù)文件和代碼文件的最后修改時間(last-modificationtime)來確定那些文件需要進行更Makefilemaketools/build執(zhí)行程序?qū)⑺袃?nèi)核編譯代碼連接和合并成一個可運行的內(nèi)核映像文件image。具體是對boot/中的GNUgcc/gassystembuild工具將這三塊組合成一個內(nèi)核映象文件image.基本編譯連接/組合結(jié)構(gòu)如圖2-20所示。

112ifyouwanttheram-diskdevice,definethistobetheRAM3sizein 45RAMDISK=#-67=as86-0-8=ld86-101112=-s-x-#?連接中包含的所有文件成員及其的符號13=gcc # CFLAGS=-Wall-O-fstrength-reduce-fomit-frame-pointer#fstrength-reducemstring-insns =cppnostdincIincludecppgccnostdincIinclude#義是不要搜索標準的頭文件 #選項指定的 18#ROOT_DEVspecifiesthedefaultroot-devicewhenmakingthe#ThiscanbeeitherFLOPPY,/dev/xxxxorempty,inwhichcase#defaultof/dev/hd6isusedby# #在的設(shè)備,這可以是軟盤(FLOPPY)、/dev/xxxx或者干脆空著,空著時#build程序(在tools/ ARCHIVES=kernel/kernel.omm/mm.ofs/fs.o# 和 ARCHIVES(歸檔文件)DRIVERSkernel/blk_drv/blk_drv.akernel/chr_drv/chr_drv.a.a #由 $(CC)$(CFLAGS)-nostdincIincludeSo$*.s$gccCFLAGS#僅使用include/ #停止(-S),從而產(chǎn)生與輸入的各個C文件對應(yīng)的匯編語言形式的#代碼文件。默認情況下所產(chǎn)生的匯編程序文件是原C文件名去掉.c#是自動目標變量,$<代表第一個先決條件,這里即是符合條件 $(CC)$(CFLAGS)-nostdincIincludeco$*.o$gccC39 Imageboot/bootsectboot/setuptools/systemtools/build#說明目標(Image) #setup文件、 中的system和build文件tools/buildboot/bootsectboot/setuptools/system$(ROOT_DEV)> $(ROOT_DEVImagedisk if=表示輸入的文件,oftools/build: #由 $(CC)$(CFLAGS)-otools/buildtools/build.c#編譯生成執(zhí)行程序build令52boot/head.o: boot/head.oinit/main.o$(ARCHIVES)$(DRIVERS)$(MATH)$(LIBS)#表示 $(LD)$(LDFLAGS)boot/head.oinit/main.o$(ARCHIVES)$(DRIVERS)$(MATH)$(LIBS)-otools/system> (cdkernel/math; (cdkernel/blk_drv;make) (cdkernel/chr_drv;make) (cdkernel;make) (cdmm;make) (cdfs;make) (cdlib;make)boot/setup: $(AS86)oboot/setup.o $(LD86soboot/setup boot/bootsect: $(AS86)-oboot/bootsect.o$(LD86)-s-oboot/bootsectboot/bootsect.otmp.s:boot/bootsect.s 15)/16116(echo-n"SYSSIZE=(";ls-ltools/system|grepsystem |cut-c25-31|tr'\012''';echo"+15)/16")>catboot/bootsect.s>>arm-fImageSystem.maptmp_makecoreboot/bootsectrm-finit/*.otools/systemtools/build(cdmm;make (cdfs;make(cdkernel;make(cdlib;makeabackup: backup.Z'cdlinux/的上一級(父)tarcflinuxlinux/執(zhí)行tarcf'|compresstar|傳遞給壓縮程序compress,并將壓縮程序的輸出存成backup.Z文件。(cd..;tarcf-linux|compress-> 重建一個目標對象的。比如當某個頭文件被改動過后,make頭文件有關(guān)的所有*.c文件。具體方法如下:#文件中'###Dependencies'行后面的所有行(118開始的行),并生成tmp_make makemake111行中的$$i實際上是$($i)的意思。這里$i是這句前面的s變量的值。sed'/\#\#\#Dependencies/q'<Makefile>(foriininit/*.c;doecho-n"init/";$(CPP)-M$$i;done)>>cptmp_make(cdfs;make(cdkernel;make(cdmm;make###init/main.o:init/main.cinclude/unistd.hinclude/sys/stat.hinclude/utime.hinclude/time.hinclude/linux/tty.hinclude/termios.hinclude/linux/mm.hinclude/signal.hinclude/asm/system.hinclude/asm/io.hinclude/stddef.h makefilemake工具程序的配置文件。Make工具程序的主要用途是能自動地決定一個含有很多源程序文件的大型程序中哪個文件需要被重新編譯。makefile的使用比較復(fù)雜,這里只是根據(jù)上面的makefile文件作些簡單的介紹。詳細說明請參考GNUmake使用手冊。告訴make如何編譯和連接一個文件。當明確時,makefile還可以告訴make運行各種命令(例如,make的執(zhí)行過程分為兩個不同的階段。在第一個階段,它所有的makefile文件以及包含的makefile文件等,記錄所有的變量及其值、隱式的或顯式的規(guī)則,并構(gòu)造出所有目標對象及其先決條件C代碼程序都將被重新編譯。每次編譯操作都產(chǎn)生一個與源程序?qū)?yīng)的目標文件(objectfile)。最終,如果任何源代碼文件被編譯過了,那么所有的目標文件不管是目標(target)...:先決條件命令過 個 則須在ke的 條變量。自動變量的值是基于目標對象及其先決條件而在命令執(zhí)行前設(shè)置的。例如,$的值表示規(guī)則的處 <$foo.o:foo.cdefs.hcc-c$(CFLAGS)$<-omake能使用習(xí)慣用法來更新一個目標對象,你可以不指定命令,寫一個不帶命令的規(guī)則或make程序?qū)鶕?jù)源程序文件的類型(程序的后綴)來判斷要使用哪個隱式規(guī)則。make程序定義隱式規(guī)則的老式方法(現(xiàn)在這種規(guī)則已經(jīng)不用了,取而代之的是使用面的’$<’值是*.c文件名。而正條make規(guī)則的含義是將*.c程序編譯成*.s代碼。

$(CC)$(CFLAGS)-nostdinc-Iinclude-S-o$*.sg文件。然而,為目標而指定命令的規(guī)則也并不一定要有先決條件。例如,與目標相關(guān)的含有刪除d)ke文件被改動過后,make就通過這些依賴關(guān)系,重新編譯與該頭文件有關(guān)的所有*.c文件。38632位的代碼。Linux16位的啟動扇區(qū)近似于In的匯編語言語法(如操作數(shù)的次序相反等。BruceEvans是minix32LinuxLinusTorvalds是很好的朋友。LinusBruceEvansUNIX類操作系統(tǒng)的知識,minix操作系統(tǒng)的不足之處也是兩個好朋友互相探討得出的結(jié)果,這激發(fā)了Linus在In386體系結(jié)構(gòu)上開發(fā)一個全新概念的操作系統(tǒng),因此Linux操作系統(tǒng)的誕生與BruceEvans也有著密切的關(guān)系。有關(guān)這個編譯器和連接器的源代碼可以從FTP服務(wù)器ftp.funet.fi上或從我的 上as[-03agjuw][-b[bin]][-lm[list]][-nname][-oobj][-ssym] -016-332-g-j-m在列表中擴展宏定義;-n后面跟隨模塊名稱(取代源文件名稱放入目標文件中-s產(chǎn)生符,后跟符名-w不顯示警告信息;ld[-03Mims[-]][-Ttextaddr][-llib_extension][-ooutfile]ld[-03Mimrs[-]][-Ttextaddr][-llib_extension][-ooutfile] -M在標準輸出設(shè)備上顯示已的符號-T后面跟隨文本址(使用適合于strtoul的格式-i分離的指令與數(shù)據(jù)段(I&D)-m在標準輸出設(shè)備上顯示已的模塊-sSystem.mapSystem.map文件中的c03441a0Bdmi_brokenc03441a4Bis_sony_vaio_laptopc03441c0bdmi_ident b bSystem.map位于使用它的軟件(例如內(nèi)核日志記錄程序klogd)能夠?qū)ふ业降牡胤?。在系統(tǒng)啟動時,如果沒有以一個參數(shù)的形式為klogd給出System.map的位置,則klogd將會在三個地方搜尋System.mapklogd,lsof,ps以及其它許多軟件,象Linux早期操作系統(tǒng)的內(nèi)核模式和體系結(jié)構(gòu)。給出了Linux0.11內(nèi)核源代碼的結(jié)構(gòu)RedHat9系統(tǒng)下編譯Linux0.11內(nèi)核時,對代碼需要進行修改的地方。最后從Linux內(nèi)核主下的makefile文件著手,第3本章主要描述boot/中的三個匯編代碼文件,見列表3-1所示。正如一章中提到的,這三個文件雖然都是匯編程序,但卻使用了兩種語法格式。bootsect.s和setup.s采用近似于In的匯編語言語In8086as86ld86head.sGNU的匯編程序格式,并且運行在保護模式下,需要用GNUas進行編譯。這是一種AT&T語法的匯編語言程序。Inx86處理器系列來講,GNUi386及以后出的CPU。不支持生成運行在實模式下的程序。最后修改時間 說5052593853641991-12-05閱讀這些代碼除了你需要知道一些一般8086匯編語言的知識以外,還要對采用In80X86微處理PC8038632位保護模式下的編程原理有些了解。所以在開始閱讀源代碼之前可CPU0xFFFF0ROM-BIOS中的Linux8086匯編語言編寫的(boot/bootsect.s)BIOS讀入到內(nèi)存絕對地節(jié)代碼(boot/setup.s)讀入到內(nèi)存0x90200處,而內(nèi)核的其它部分(system模塊)則被讀入到從地址512KBLinux系統(tǒng)啟動時這幾個程序或模塊在內(nèi)存中的動態(tài)位置。其中,每一豎條框代表某一時刻內(nèi)存中 632位運行方式的設(shè)置啟動被完成IDT、GDTLDT被加載,處理器和協(xié)處理器也已確認,init/main.cmain()boot/head.S中的,setupROMBIOS中的中斷調(diào)用來獲取機器的一些參數(shù)(例如顯示卡模式、硬盤參數(shù)表等BIOS0x400字節(jié)(1Kb)的中斷向量表,因此需要在使用完BIOS的中斷調(diào)用后才能將這個區(qū)域覆蓋掉。1個扇區(qū)PCROMBIOSBIOS0x7C00處,然后將自己bootsect的后面位置(0x90200),BIOS0x13取磁盤參數(shù)表中當前啟動引導(dǎo)盤的參數(shù),接著在屏幕上顯示“Loadingsystem...”system0x10000開盤的類型和種類(1.44MA盤嗎?)root_dev(0x508地址處),最后長跳轉(zhuǎn)到setup程序的開始處(0x90200)執(zhí)行setup程序。1

!SYS_SIZEisthenumberofclicks(16bytes)tob

溫馨提示

  • 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)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論