Linux實現(xiàn)原理-虛擬內(nèi)存技術(shù)簡析_第1頁
Linux實現(xiàn)原理-虛擬內(nèi)存技術(shù)簡析_第2頁
Linux實現(xiàn)原理-虛擬內(nèi)存技術(shù)簡析_第3頁
Linux實現(xiàn)原理-虛擬內(nèi)存技術(shù)簡析_第4頁
Linux實現(xiàn)原理-虛擬內(nèi)存技術(shù)簡析_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

Linux實現(xiàn)原理—虛擬內(nèi)存技術(shù)簡析虛擬內(nèi)存技術(shù)虛擬內(nèi)存技術(shù)是操作系統(tǒng)實現(xiàn)的一種高效的物理內(nèi)存管理方式,具有以下作用:使得進程間彼此隔離:通過將物理內(nèi)存和虛擬地址空間聯(lián)系起來,并將虛擬地址空間與進程一一對應(yīng),每個進程都認(rèn)為自己擁有了整個物理內(nèi)存,使得進程之間彼此隔離。這讓操作系統(tǒng)在運行多個進程的同時也保障了內(nèi)存訪問的安全。使得進程共享物理內(nèi)存:將物理內(nèi)存進行虛擬化后,多個進程可以同時共享同一塊物理內(nèi)存。提升物理內(nèi)存利用率:有了虛擬地址空間后,操作系統(tǒng)只需要將進程當(dāng)前正在使用的部分?jǐn)?shù)據(jù)或指令加載入物理內(nèi)存,沒有在使用的部分?jǐn)?shù)據(jù)或指令則可以存儲在外存中,而不需要將整個進程的數(shù)據(jù)或指令全部載入物理內(nèi)存。這使得操作系統(tǒng)可以在相對較小的物理內(nèi)存下運行更多的進程,從而提升了物理內(nèi)存的利用率。方便內(nèi)存管理:虛擬內(nèi)存技術(shù)將物理內(nèi)存分割成若干塊,每塊都可以分配給不同的進程使用,這使得操作系統(tǒng)可以更加靈活地管理內(nèi)存。如物理內(nèi)存分配、回收等。頁式內(nèi)存管理技術(shù)頁式內(nèi)存管理技術(shù)是Linux實現(xiàn)的一種虛擬內(nèi)存技術(shù),其基本思想是將物理內(nèi)存和虛擬內(nèi)存都分割成多個固定大小的Page(頁),然后對這些Pages進行編址,并通過PageTable(頁表)將它們一一映射起來。當(dāng)CPU訪問虛擬地址空間時,Linux會通過PageTable將虛擬地址轉(zhuǎn)換為物理地址。VirtualAddress(虛擬地址):操作系統(tǒng)和應(yīng)用程序使用的虛擬內(nèi)存地址。PhysicalAddress(物理地址):實際的物理內(nèi)存地址。Linux通過頁式內(nèi)存管理技術(shù),除了能夠高效地管理物理內(nèi)存之外,還提供了許多額外的虛擬內(nèi)存功能,例如:進程隔離、內(nèi)存保護、共享物理內(nèi)存等。虛擬地址格式與頁表(32bit系統(tǒng))在x8632bitLinux系統(tǒng)中,虛擬地址(也稱為線性地址,LinearAddress)的格式由3部分組成,總長度為32bit,尋址范圍為2^32,最大可描述空間為4G。PageTableDirectory(10bit)PageTableEntry(10bit)Offset(12bit)在Kernel中用于對虛擬地址進行尋址的數(shù)據(jù)結(jié)構(gòu)稱為KernelPageTable(內(nèi)核頁表),包括:頁表目錄(PageDirectory):可包含1024個目錄項。目錄項(DirectoryEntry):每個目錄項指向一個頁表,即有1024個頁表。頁表(PageTable):大小為4KB,頁表項的大小為4B,即一個頁表可包含1024個頁表項。頁表項(PageTableEntry):每個頁表項指向一個頁。屬性標(biāo)記:用于將每個頁表項標(biāo)記為只讀、可寫、只執(zhí)行等,以控制內(nèi)存的訪問權(quán)限和緩存行為??梢?,32bit系統(tǒng)中的2級頁表結(jié)構(gòu),最多可以映射1024*1024個Pages。而對于大于4GB的物理地址空間,則需要使用多級級頁表結(jié)構(gòu),以支持更大的物理內(nèi)存空間。虛擬地址格式與頁表(64bit系統(tǒng))在x8664bit系統(tǒng)中,可以描述的最長地址空間為2^64(16EB),遠遠超過了目前主流內(nèi)存卡的規(guī)格,所以在Linux中只使用了48bit長度,尋址空間為2^48(256TB),UserSpace和KernelSpace各占128T。尋址空間分別為:UserSpace:0x0000000000000000~0x00007FFFFFFFF000,高16bit全0。CanonicalAddressSpace:0x00007FFFFFFFF000-0xFFFF800000000000,無效地址空間。KernelSpace:0xFFFF800000000000~0xFFFFFFFFFFFFFFFF,高16bit全1。由于內(nèi)存空間的擴大,x8664bit系統(tǒng)中的虛擬地址格式由5部分組成,占64bit中的48bit。相應(yīng)的,LinuxKernel在v2.6.10中實現(xiàn)了四級頁表,后來又在v4.11中引入了五級的頁表結(jié)構(gòu)。就四級頁表而言,虛擬內(nèi)存空間被劃分成了4個層次結(jié)構(gòu),每一級都有一個頁表來記錄該層次的映射關(guān)系。PGD(PageGlobalDirectory,全局頁目錄)PUD(PageUpperDirectory,上級頁目錄)PMD(PageMiddleDirectory,中間頁目錄)PTE(PageTableEntry,頁表項)當(dāng)CPU需要訪問一個虛擬地址時,會執(zhí)行以下頁表遍歷流程:首先根據(jù)虛擬地址的GLOBALDIR(9bit),確定在PGD中的頁表項,開始尋址PUD。再根據(jù)虛擬地址中的UPPERDIR(9bit),確定PUD中的頁表項,開始尋址PMD。再根據(jù)虛擬地址中的MIDDLEDIR(9bit),確定PMD中的頁表項,開始尋址PTE。再根據(jù)虛擬地址中的TABLEID(9bit),確定PTE中的頁表項,開始尋址PhysicalPage(物理內(nèi)存頁框)。最后根據(jù)虛擬地址中的OFFSET(12bit),確定PhysicalPage中的PageLane(頁條)。在頁表遍歷的過程中,如果找到對應(yīng)的物理頁框,則可以進行對應(yīng)的內(nèi)存讀寫操作。反之,如果遇到了尋址失敗的情況,則說明對應(yīng)的物理頁框沒有被分配或者被換出到外存了,此時需要進行相應(yīng)的頁表調(diào)度和頁表交換操作。四級頁表的優(yōu)點是它可以映射非常大的虛擬內(nèi)存空間,并且每個進程的頁表都是獨立的,相互干擾。缺點是每次訪問內(nèi)存都需要遍歷四級頁表,這會導(dǎo)致一定的性能損失。并且,當(dāng)Linux設(shè)定的虛擬頁大小越小時,單個進程中的頁表項和虛擬頁也就越多,頁表的層級也可能越多,查詢性能就越低。同時也需要注意,頁面并非是越大越好,因為過大的頁面會造成內(nèi)存碎片,降低了內(nèi)存的利用率。因此,Linux采用了一些優(yōu)化措施,如TLB(TranslationLook-asideBuffer)緩存等,來加速頁表遍歷的過程。CPUMMU虛實地址轉(zhuǎn)換Linux虛實地址轉(zhuǎn)換功能,除了需要由Kernel實現(xiàn)的內(nèi)核頁表(PageTable)數(shù)據(jù)結(jié)構(gòu)之外,還需要硬件層面的CPUMMU(MemoryManagementUnit,存儲管理單元)支持。MMU(MemoryManagementUnit,內(nèi)存管理單元)內(nèi)嵌在CPU芯片上,它是一個專用的硬件,利用存放在MainMemory中的PageTable來輔助完成虛實地址之間的動態(tài)翻譯,而PageTable的內(nèi)容就交由Kernel來統(tǒng)一管理。當(dāng)CPU訪問虛擬地址時,MMU首先將虛擬地址的高位部分作為頁表的索引,查找對應(yīng)的頁表項。頁表項中存儲了與虛擬頁對應(yīng)的物理頁的起始地址以及一些標(biāo)志位,如是否可讀、可寫等。然后,MMU將虛擬地址的低位部分作為偏移量,加上物理頁的起始地址,得到實際的物理地址。TLS快表轉(zhuǎn)換TLB(TranslationLook-asideBuffer,翻譯旁路緩沖器)同樣是內(nèi)嵌在CPU芯片上的一個專用硬件,作為緩存,旁掛在MMU上,緩存了最近訪問過的虛擬地址與物理地址之間的映射關(guān)系,以便在下次訪問時快速地進行翻譯。TLB的空間非常有限,一般只可緩存幾十個到數(shù)百個條目。通過TLB,操作系統(tǒng)可以旁路掉多級頁表遍歷的流程,只需要在TLB中執(zhí)行一次高速訪問即可,前提是沒有TLBMiss(緩存失效)。如果Miss的話,就會回到常規(guī)的頁表遍歷流程,然后再利用局部性原理去更新TLB。虛擬地址空間與CPU運行模式為了保障多任務(wù)實時操作系統(tǒng)運行的安全性和穩(wěn)定性,Intelx86CPU提供了Ring0-3這4種不同的運行模式,而Linux只使用了其中的Ring0(特權(quán)指令模式)和Ring3(非特權(quán)指令模式),為虛擬地址空間提供了2級保護機制。相應(yīng)的,在32bitLinux系統(tǒng)中,大小為4G的虛擬地址空間,被分成了2個部分:UserSpace(0x0~0xBFFFFFFF,0~3G):每個UserProcess都有自己的UserSpace且互相隔離。運行在CPURing3(用戶模式)模式,UserProcess的代碼被限制了可以執(zhí)行的操作以及可以訪問的資源范圍;KernelSpace(0xC0000000~0xFFFFFFF,3~4G):屬于Kernel的KernelSpace。運行在CPURing0(內(nèi)核模式)模式,Kernel代碼沒有被限制,可以執(zhí)行任何操作并且可以訪問任何資源。所以,Linux中的PageTable也可以被分為2種:內(nèi)核頁表區(qū):用于KernelSpace高端內(nèi)存映射區(qū)與物理地址空間之間的映射。進程頁表區(qū):每個UserProcess擁有自己的頁表,用于進程虛擬地址空間與物理地址空間之間的映射。另外,UserSpace可以通過SCI(系統(tǒng)調(diào)用接口)來訪問或操作KernelSpace的代碼和數(shù)據(jù),同時也會觸發(fā)CPU運行模式的切換。例如:C標(biāo)準(zhǔn)庫中的malloc()函數(shù)底層調(diào)用了sbrk()或brk()SCI來分配堆內(nèi)存;printf()函數(shù)底層調(diào)用了wirte()SCI來輸出字符串等等。虛擬地址空間的布局(32bit系統(tǒng))從上圖可以看出Linux對虛擬地址空間作了復(fù)雜的分段布局,主要是為了實現(xiàn)更加高效的內(nèi)存管理和保護機制。以UserSpace為例:持久化的程序流代碼(順序程序流、條件程序流、循環(huán)程序流)存儲在TestSegment中。持久化的、且初始化的常量、全局變量、靜態(tài)變量(包括靜態(tài)全局變量、靜態(tài)局部變量)存儲在DataSegment中。持久化的、但未初始化的全局變量、靜態(tài)變量(包括靜態(tài)全局變量、靜態(tài)局部變量)存儲在BSSSegment中。臨時的函數(shù)局部變量存儲在StackSegment中。臨時由用戶自主申請的數(shù)據(jù)存儲HeapSegment或MMAPSegment中。劃分不同的存儲空間更有助于針對不同的數(shù)據(jù)內(nèi)容進行合理的訪問和存儲規(guī)劃。例如:提高CPUCache利用率:將指令區(qū)、持久數(shù)據(jù)區(qū)、動態(tài)數(shù)據(jù)區(qū)進行分離,有利于應(yīng)用局部性原理來發(fā)揮出CPUInstructionCache(指令緩存)和DataCache(數(shù)據(jù)緩存)的優(yōu)勢。節(jié)省內(nèi)存空間:如果系統(tǒng)中運行多個該程序的副本時,指令區(qū)中的ReadOnly數(shù)據(jù)可被共享,物理內(nèi)存實際上只需要存儲一份。UserSpace在UserSpace中,每個UserProcess都有一個task_struct(進程描述符)。structtask_struct{pid_tpid;//UserProcessIDpid_ttgid;//KernelThreadIDstructfiles_struct*files;//文件描述符structmm_struct*mm;//內(nèi)存映射描述符...}其中,除了EnvironmentVariables(程序運行時環(huán)境變量)和Command-linearguments(程序運行指令行參數(shù))之外,進程虛擬地址空間的內(nèi)存布局都通過mm_struct結(jié)構(gòu)體來進行描述。StackSegment(用戶棧)UserProcess下屬的每個UserThread都有屬于自己的用戶線程棧。主要用于存儲以下信息:存儲函數(shù)調(diào)用信息(ProcedureActivationRecord,過程活動記錄)或棧幀(StackFrame)。存儲函數(shù)內(nèi)部的非靜態(tài)(Non-static)變量;提供臨時存儲區(qū),使用C標(biāo)準(zhǔn)庫alloca()函數(shù)可動態(tài)申請棧內(nèi)內(nèi)存。StackSegment的空間具有“靜態(tài)分配"和“動態(tài)分配”這2種使用形勢。其中,靜態(tài)分配由C編譯器自動分配和管理,主要應(yīng)用在函數(shù)處理流程。而動態(tài)分配則由程序通過alloca()函數(shù)主動申請和釋放。例如:在一次函數(shù)調(diào)用中,C編譯器依次入棧的數(shù)據(jù)包括:主調(diào)函數(shù)下一條語句(指令);被調(diào)函數(shù)的返回值地址;被調(diào)函數(shù)的實際參數(shù);被調(diào)函數(shù)局部變量等。通過先進后出(FILO)的數(shù)據(jù)結(jié)構(gòu),使得被調(diào)函數(shù)退出后,可以繼續(xù)執(zhí)行主調(diào)函數(shù)的語句。StackSegment是一塊連續(xù)的空間,運行時大小可以由Kernel動態(tài)調(diào)整(向下增長),且最大容量RLIMIT_STACK(8M)由系統(tǒng)預(yù)先定義,用戶也可以通過ulimit-s指令來查看和設(shè)定棧的最大值。$ulimit-s8192當(dāng)程序入棧數(shù)據(jù)超出容量之后,就會觸發(fā)StackOverflow(溢出)錯誤,此時程序收到一個SegmentationFault(段錯誤)異常。函數(shù)調(diào)用棧的工作原理程序每執(zhí)行一次函數(shù)調(diào)用都會在Stack中生成一個棧幀(StackFrame),對應(yīng)著一個未運行完的主調(diào)函數(shù),用于存儲被調(diào)函數(shù)的執(zhí)行環(huán)境信息,包括:函數(shù)實際參數(shù)、函數(shù)局部變量、函數(shù)返回值地址等等。棧幀主要通過兩個指針寄存器來實現(xiàn):ebp(幀指針):指向幀底,作為基址指針,不會移動。esp(棧指針):指向棧頂,可以移動,通過移動esp來訪問棧幀中的數(shù)據(jù)。ebp到esp之間的地址空間就是用于存儲當(dāng)前被調(diào)函數(shù)執(zhí)行環(huán)境信息的空間。另外,StackSegment很可能會同時存在多個棧幀(函數(shù)嵌套調(diào)用),此時多個棧幀會根據(jù)函數(shù)調(diào)用順序在StackSegment中先入后出。例如:雖然esp會隨著當(dāng)前函數(shù)的入棧和出棧而不斷移動,但由于ebp的存在,所以當(dāng)前函數(shù)棧幀的邊界始終是清晰的。當(dāng)被調(diào)函數(shù)退出后,ebp就會跳到主函數(shù)棧幀的底部,esp也會隨其自然的來到主函數(shù)棧幀的頭部。MemoryMappingSegment(內(nèi)存映射段)MemoryMappingSegment(內(nèi)存映射段)的空間通過mmap()SCI(系統(tǒng)調(diào)用接口)來使用,用于將外存(e.g.硬盤)中的一個文件、或一段物理內(nèi)存直接映射到MemoryMappingSegment中,而后UserProcess就可以采用指針的方式來訪問一段內(nèi)存,而不必再調(diào)用read()/write()等SCI。mmap()是一種高效的I/O方式。MemoryMappingSegment主要有2類應(yīng)用場景:Filemappings(文件映射):在程序裝載過程中,將程序所需要#include的.so動態(tài)共享庫文件(Dynamicsharelibraries)加載到MemoryMappingSegment內(nèi)存空間。Anonymousmappings(匿名內(nèi)存映射):C標(biāo)準(zhǔn)庫malloc()函數(shù)的底層實現(xiàn)方式之一就是對大于MMAP_THRESHOLD(默認(rèn)為128KB)的空間申請,會調(diào)用mmap()SCI從MemoryMappingSegment中分配,而不是調(diào)用sbrk()或brk()SCI從Heap申請。MemoryMappingSegment的空間大小同樣可以由Kernel動態(tài)調(diào)整(向上增長)。HeapSegment(運行時堆)HeapSegment(運行時堆)的空間由程序自行使用,包括分配和釋放。例如:開發(fā)者可通過C標(biāo)準(zhǔn)庫malloc()函數(shù)申請并返回void*(無類型指針),且無名稱,只能通過指針訪問。在Kernel層面通過堆管理器來管理HeapSegment的空間。堆管理器通過鏈表存儲結(jié)構(gòu)來記錄HeapSegment空間的使用情況,記錄了包括:空閑的內(nèi)存地址、已使用的內(nèi)存地址等。當(dāng)程序申請一塊內(nèi)存時,堆管理器會遍歷鏈表尋找第一個空間大于所申請空間的節(jié)點,并返回地址給程序,然后將該節(jié)點從空閑鏈表中刪除。所以Heap空間中的多個內(nèi)存塊之間很可能是不連續(xù)的。當(dāng)目前的HeapSegment已經(jīng)沒有足夠的空間時(可能由于內(nèi)存碎片太多導(dǎo)致的),那么堆管理器可能會通過brk()或sbrk()SCI進行動態(tài)調(diào)整(向上增長),實際上是通過調(diào)整HeapSegment末端的break指針來實現(xiàn)。HeapSegment的空間總大小受到CPU架構(gòu)和操作系統(tǒng)位數(shù)影響,例如:32bit架構(gòu)的HeapSegment最大可達2.9G空間。應(yīng)用程序裝載與數(shù)據(jù)段當(dāng)開發(fā)者經(jīng)過編碼、編譯、匯編、鏈接一個C程序后就得到了一個可執(zhí)行程序的文件。然后,就需要通過程序裝載器(Loader)將可執(zhí)行文件加載到UserSpace中并啟動一個UserProcess。在Linux上,可執(zhí)行文件采用的是ELF(ExecutableandLinkableFileFormat,可執(zhí)行與可鏈接文件格式)格式。ELF文件由4部分組成,分別是:ELFHeaderProgramHeaderTable(程序頭表)Sections(節(jié))SectionHeaderTable(節(jié)頭表)其中,位于ProgramHeaderTable和SectionHeaderTable之間的都是Sections,這些Sections中的數(shù)據(jù)會在程序啟動時被加載到相應(yīng)的進程虛擬地址空間中。關(guān)鍵的Sections包括以下幾個:.bss:存儲未初始化的全局變量和靜態(tài)變量。.data:存儲已初始化的全局變量和靜態(tài)變量。.rodata:存儲只讀數(shù)據(jù)(e.g.常量)。.text:存儲已編譯程序的機器指令代碼。.debug:調(diào)試符號表,調(diào)試器用此段的信息幫助調(diào)試。數(shù)據(jù)段(BSSSegment和DataSegment)BSSSegment和DataSegment常被合并稱為“數(shù)據(jù)段”,都用于存儲全局變量和靜態(tài)變量,區(qū)別于存儲在StackSegment中的函數(shù)局部變量。BSS(BlockStartedbySymbol,未初始化的數(shù)據(jù)段):可讀寫,主要存儲了從ELF.bsssection中加載的數(shù)據(jù),包括:1)已定義,但未初始化的全局變量和靜態(tài)變量;2)已定義,且初始值為0的全局變量和靜態(tài)變量,例如C編譯器中的空指針。DataSegment(已初始化的數(shù)據(jù)段):可讀寫,主要存儲了從ELF.datasection中加載的數(shù)據(jù),包括:已定義、且已初始化、且初值不為0的全局變量、靜態(tài)變量和常量。所以,DataSegment也被稱為“靜態(tài)存儲區(qū)(Staticdataarea)”。ELF.bsssection的特別之處在于沒有具體的數(shù)值,所以只需要記錄下全局變量和靜態(tài)變量所需要的內(nèi)存空間大小即可,但并不會分配真實的內(nèi)存空間,即:只記錄了全局變量和靜態(tài)變量在虛擬地址空間中的開始和結(jié)束地址。當(dāng)程序加載器(Loader)將ELF.bsssection加載到BSSSegment后,這些數(shù)據(jù)會被C編譯器自動的初始化為0或NULL。這樣可以有效的減少了Cobjectfile的體積。例如:對于intarr0[10000]={1,2,3,…}和intar1[10000]這兩個數(shù)組而言:arr0存儲在DataSegment,記錄了每個數(shù)組元素的數(shù)值。arr1存儲在BSSSegment,只記錄了arr1的起始和結(jié)束地址,直到程序啟動時才被編譯器在相應(yīng)的虛擬地址空間中刷0。顯著的減少了可執(zhí)行文件的大小。TextSegment(代碼段)TextSegment(代碼段)主要存儲了從ELF.textsection中加載的機器指令。TextSegment中的數(shù)據(jù)只能讀不能寫,但可以被執(zhí)行,即:TextSegment中的數(shù)據(jù)是可共享的,可以被其他的進程執(zhí)行。例如:機器中有數(shù)個進程運行相同的一個程序,那么它們就可以使用同一個代碼段??梢姡琔serSpace劃分了明確的“數(shù)據(jù)區(qū)”和“指令區(qū)",且數(shù)據(jù)區(qū)對于進程而言可讀寫,而指令區(qū)對于進程只讀,以防止程序指令被誤改。內(nèi)存缺頁中斷基于Linux虛擬內(nèi)存管理技術(shù),每個UserProcess都擁有自己獨立的虛擬地址空間,當(dāng)一個UserProcess被Kernel加載并運行時,無需要一次性將UserProcess所有數(shù)據(jù)都加載到MainMemory中,而是當(dāng)通過PageTable缺頁中斷的方式來動態(tài)加載。虛擬地址的頁表遍歷過程中,當(dāng)訪問到某個頁面時,通過頁表項中的有效位,可以得知此頁面是否在內(nèi)存中,如果不存在,則通過缺頁異常,將磁盤對應(yīng)的數(shù)據(jù)拷貝到內(nèi)存中,如果沒有空閑內(nèi)存,則選擇犧牲頁面,替換掉其他頁面。在這個時候,被內(nèi)存映射的文件實際上成了一個分頁交換文件。KernelSpaceKernelSpace與物理地址空間的映射關(guān)系區(qū)別于UserSpace只擁有虛擬地址空間。KernelSpace除了虛擬地址空間之外,還直接擁有一部分的物理地址空間。也就是說KernelSpace具有2種地址映射關(guān)系,如下圖所示。直接映射(LinearMapped):KernelSpace虛擬地址空間中的3G~3G+896M與物理地址空間的0~896M直接一對一映射,擁有最高的效率。動態(tài)映射(DynamicMapped):KernelSpace虛擬地址空間中的高端內(nèi)存映射區(qū)(0xF8000000~0xFFFFFFFF)動態(tài)的與物理地址空間896M~4G中的某塊物理頁面建立映射(通過PageTable),即:在有需要的時候才建立映射,待使用完之后就釋放映射,以供其它物理頁面映射。物理地址空間布局基于不同的用途,Linux將物理內(nèi)存劃分為3個ZONEs,從地址低到高為:ZONE_DMA(0~16M):是Kernel直接映射的物理地址空間。ZONE_NORMAL(16M~896M):是Kernel直接映射的物理地址空間,Kernel將需要頻繁使用的數(shù)據(jù)存放于此。ZONE_HIGHMEM(896M~4G):是Kernel動態(tài)映射到物理地址空間,Kernel將不常用數(shù)據(jù)存放于此,只在要訪問這些數(shù)據(jù)時才建立映射關(guān)系。最終,通過結(jié)合兩種映射方式,LinuxKernel可以完全接管整個4G物理內(nèi)存空間。如下圖所示,藍色區(qū)域為直接映射空間,綠色區(qū)域為動態(tài)映射空間,棕色區(qū)域為動態(tài)映射頁面。物理直接映射區(qū)根據(jù)UserProcess對KernelSpace訪問權(quán)限的不同,還可以將KernelSpace分為“進程私有”和“進程共享”這2塊區(qū)域。進程私有區(qū)域:每個進程都有單獨的內(nèi)核棧、頁表、task結(jié)構(gòu)以及mem_map結(jié)構(gòu)等。進程共享區(qū)域:屬于所有進程共享的內(nèi)存區(qū)域,包括:物理存儲器、內(nèi)核數(shù)據(jù)和內(nèi)核代碼區(qū)域。KernelSpace中的物理直接映射區(qū),屬于“進程共享區(qū)域",是為了讓KernelSpace或者UserSpace可以直接訪問某些特殊的物理內(nèi)存區(qū)域。這些物理內(nèi)存區(qū)域包括:ZONE_DMA:NIC、GPU此類I/O外設(shè)所提供的DMAController只能對內(nèi)存的前16M進行尋址。為了方便設(shè)備驅(qū)動程序的實現(xiàn),Linux通過物理直接映射區(qū),使得Kernel和UserProcess可以直接訪問這些外設(shè)的存儲器。此外,在ZONE_DMA中還劃分了用于BIOSROM和VGA適配器的區(qū)域,地址為640K~1M。ZONE_NORMAL:常規(guī)內(nèi)存區(qū)域,沒有特殊的使用限制,主要用于UserProcess和Kernel之間的交互,以及作為文件緩存加快文件系統(tǒng)的訪問速度,避免頻繁地讀寫磁盤。例如:存放KernelImage(內(nèi)核代碼)、mem_map數(shù)組等數(shù)據(jù)??梢?,物理直接映射區(qū)使得Kernel和UserProcess得以更方便地訪問一些特殊的物理內(nèi)存區(qū)域,從而簡化了操作系統(tǒng)和設(shè)備驅(qū)動程序的編寫。DMA直接內(nèi)存訪問DMA(DirectMemoryAccess,直接內(nèi)存訪問)指的是主機的I/O外設(shè)對MainMemory的直接訪問。有了DMA機制之后,外設(shè)跟主存之間的數(shù)據(jù)交互主要由DMAController來完成的,從而避免了CPU(包括MMU)的參與。高端內(nèi)存映射區(qū)物理內(nèi)存中的ZONE_NORMAL(高端內(nèi)存區(qū)域)大小為4G-896M=3200M,遠遠大于KernelSpace剩余的1G-896M=128M虛擬地址空間。所以Kernel對ZONE_NORMAL的訪問需要采用動態(tài)映射的方式。KernelSpace中的128M統(tǒng)稱為“高端內(nèi)存映射區(qū)”,主要有以下3個部分組成:FixingKernelMa

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論