版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、1 / 29 文檔可自由編輯打印LinuxLinux 虛虛 存存 分分 析析 報報 告告方方 存存 好好第一章第一章 前前 言言2第二章第二章 LINUX 虛存管理概述虛存管理概述31、LINUX虛存管理的基本特點32、LINUX虛存管理的主要實現(xiàn)技術(shù)3第三章第三章 LINUX 虛存管理數(shù)據(jù)結(jié)構(gòu)虛存管理數(shù)據(jù)結(jié)構(gòu)51、32-BIT虛擬地址52、LINUX的多級頁表結(jié)構(gòu)53、頁表項的格式64、動態(tài)地址映射75、用戶進程的虛擬內(nèi)存結(jié)構(gòu)86、我們的工作10第四章第四章 PROCESS 的虛存管理數(shù)據(jù)結(jié)構(gòu)的建立、維護、拆除及相關(guān)系統(tǒng)調(diào)用流程的虛存管理數(shù)據(jù)結(jié)構(gòu)的建立、維護、拆除及相關(guān)系統(tǒng)調(diào)用流程111、進
2、程的載入、創(chuàng)建及內(nèi)存管理數(shù)據(jù)結(jié)構(gòu)和鏈結(jié)關(guān)系的建立112、數(shù)據(jù)結(jié)構(gòu)及鏈結(jié)關(guān)系的拆除(SYS_EXIT)133、缺頁中斷服務(wù)14第五章第五章 主要函數(shù)分析主要函數(shù)分析16MEMORY.C16MMAP.C22第六章第六章 后記后記292 / 29 文檔可自由編輯打印第一章第一章 前前 言言Linux 是一個功能強大的操作系統(tǒng),而內(nèi)存管理則是操作系統(tǒng)的核心,它負責管理計算機系統(tǒng)的存儲器。作為操作系統(tǒng)的核心,必須能夠克服物理內(nèi)存的局限,使用戶進程在透明方式下,擁有比實際物理內(nèi)存大得多的內(nèi)存。其策略之一就是使用虛擬內(nèi)存。Linux成功地實現(xiàn)了以虛擬內(nèi)存為核心的內(nèi)存管理策略,強大得分頁機制,公平得交換方式,
3、各類有效得高速緩存,以及以頁保護為主得保護措施等。內(nèi)存管理的目的是要盡可能地方便用戶。同時 Linux 系統(tǒng)通過對用戶進程虛存的有效管理,作到了虛存對一般用戶和 Linux程序員的透明。本文首先闡述了 Linux 虛存管理以基本特點和主要實現(xiàn)技術(shù),并分析了 Linux 虛存管理的主要數(shù)據(jù)結(jié)構(gòu)及其相關(guān)關(guān)系。圍繞它的建立、維護、使用和拆除,作了一個粗淺的剖析,因本人水平有限,有不當之處,請老師指正。同時應(yīng)該指出的是本文所做的工作離不開同組的林濤、徐玫峰和范昭偉同學(xué)的幫助,謝謝他們。3 / 29 文檔可自由編輯打印第二章第二章 Linux 虛存管理概述虛存管理概述Linux 的內(nèi)存管理采用頁式管理,
4、使用多級頁表,動態(tài)地址轉(zhuǎn)換機構(gòu)與主存、輔存共同實現(xiàn)虛擬內(nèi)存:每個用戶 Process 擁有 4GB 的虛擬地址空間,Process 在運行過程中可以動態(tài)浮動和擴展,為用戶提供了透明的、靈活有效的內(nèi)存使用方式,下面簡述 Linux 虛存管理以基本特點和主要實現(xiàn)技術(shù):1、 Linux 虛存管理的基本特點虛存管理的基本特點1.更大的地址空間。虛擬內(nèi)存可以是系統(tǒng)實際擁有的物理內(nèi)存的若干倍。因而它使得操作系統(tǒng)看起來擁有比實際大得多的內(nèi)存。2.合理的物理內(nèi)存分配。Linux 通過共享和交換策略,使各個運行的進程能公平地共享內(nèi)存。3.保護。Linux 存儲管理子系統(tǒng)為每一內(nèi)存頁設(shè)置了“上鎖位” ,在線性地址
5、及每級頁表頁項上設(shè)置了“讀/寫”位,這樣來確保某一個進程不受其他進程的干擾。即使某一個進程失敗了,也不會影響到其他進程和操作系統(tǒng)本身。4.共享虛擬內(nèi)存Linux 實現(xiàn)的虛擬內(nèi)存允許兩個進程之間互相共享內(nèi)存,例如:共享的庫。在這種情形之下,庫代碼僅存在于一個進程,而不需要為每一個應(yīng)用都復(fù)制一份。2、 Linux 虛存管理的主要實現(xiàn)技術(shù)虛存管理的主要實現(xiàn)技術(shù)1、 請求調(diào)頁(demanding paging)與內(nèi)存擴展用戶 Process 創(chuàng)建時,并不是將它所需所有頁都分配給相應(yīng)物理頁。開始時只裝入頁面中 Process 的第一個頁面,其他頁根據(jù) Process 運行過程的請求從外存調(diào)入所需頁面,當
6、Process 訪問一個頁表項 P 位為 0 的頁中地址時,表示此頁不在主存中,將產(chǎn)生缺頁中斷,系統(tǒng)調(diào)用 handle_mm_fault()處理訪問異常,為之分配相應(yīng)物理頁后,它再調(diào)用 s()函數(shù),從外存中讀入該頁面。Linux 是一種請求式分頁存貯管理,這才使之可以運行大于主存空間的 Process。2、 頁換出策略4 / 29 文檔可自由編輯打印內(nèi)存中頁面不足時,Linux 使用頁面 AGE 技術(shù)實現(xiàn)了頁淘汰策略的最近最少使用(LRU)算法:即每次換出時,總是選擇最老的頁換出,對易于從其他設(shè)備上獲取的非臟(not dirty)頁面。Linux 采用丟棄(discarding)技術(shù),如果發(fā)生
7、過寫操作,則將該頁寫入系統(tǒng)的 S 中,這樣就可以加快換入的速度。3、 內(nèi)存共享Linux 將內(nèi)存劃分為 4K 大小的頁面,為內(nèi)存共享提供了基礎(chǔ):(1)不同進程間頁面共享時,可令共享該頁的 Process 的頁表項(pte)均指向該頁。(2)對 kernel 代碼和數(shù)據(jù)段的共享,通過 Process 創(chuàng)建時 fork() 函數(shù)將 kernel 代碼和數(shù)據(jù)段映射到用戶虛存的 3GB4GB 的空間中去,所以每個 Process 都可以通過一定方式共享kernel 的代碼和數(shù)據(jù)段。4、 內(nèi)存保護采用了“Hole”技術(shù)、虛存段的保護、地址轉(zhuǎn)換機構(gòu)、頁表存取控制位(R/W 位)等技術(shù)實現(xiàn)了內(nèi)存保護?!癏o
8、le”技術(shù) 物理內(nèi)存前 4K 是一空頁(empty_zero_page) ,用來捕獲 NULL 指針的異常訪問。在 Process 每個虛存段后,都有一個“4K”的“Hole” ,用來捕獲虛存段的越界訪問。虛存段保護方式 主存中虛存段的全部或部分可以設(shè)為保護方式,防止非法訪問。頁表項存取控制位(R/W 位) 頁表項以“R/W”位表示此頁的存取權(quán)限“1”為可讀寫, “0”為不可讀寫,可用來防止越權(quán)訪問。地址轉(zhuǎn)換機構(gòu) 分頁存貯管理方法中,地址轉(zhuǎn)換機構(gòu)進行的頁面映象實際上防止了各 Process 的主存塊間互不干擾,起到 Process 隔離的作用。5、 動態(tài)地址變換利用 i386 的地址變換機構(gòu)
9、Linux 實現(xiàn)了動態(tài)地址變換,Process 執(zhí)行時訪問到某一虛擬地址時才確定其對應(yīng)的物理地址。這種方式為 Process 存貯塊的動態(tài)和動態(tài)擴展提供了基礎(chǔ)。5 / 29 文檔可自由編輯打印第三章第三章 Linux 虛存管理數(shù)據(jù)結(jié)構(gòu)虛存管理數(shù)據(jù)結(jié)構(gòu)1、32-bit 虛擬地址虛擬地址在 Linux 中,4GB 的虛存需通過 32-bit 地址進行尋址。 (Linux 中虛擬地址與線形地址為同一概念)虛擬地址被分割成 3 個子位段,其中 2 個子位段包含 10 位, 1 個子位段包含 12 位,如圖 2.1 所示:123圖 1 32 位虛擬地址3 個子位段分別表示不同含義:子位段 1 指向被稱作
10、頁目錄(PGD)的一張表,子位段 2 指向被稱作頁表(PTE)的一張表,子位段 3 指向頁內(nèi)地址。2、Linux 的多級頁表結(jié)構(gòu)的多級頁表結(jié)構(gòu)標準的 Linux 的虛存頁表為三級頁表,依次為頁目錄(Page Directory-PGD)、中間頁目錄(Page Middle Directory-PMD)、頁表(Page Table)PTE) 。如圖 2.2 所示。 PGD PMD PTE PAGE FRAME圖 2 Linux 的多級頁表結(jié)構(gòu)在 i386 機器上 Linux 的頁表結(jié)構(gòu)實際為兩級,PGD 和 PMD 頁表是合二為一的。所有有關(guān) PMD 的操作實際上是對 PGD 的操作。所以原代碼
11、中形如*-pgd-*()和*-pmd-*()的函數(shù)實現(xiàn)的功能也是一樣的。6 / 29 文檔可自由編輯打印頁目錄(PGD) 是一個大小為 4K 的表,每一個 process 只有一個頁目錄,以 4 字節(jié)為一個表項,分成 1024 個表項(或稱入口點);該表項的值為所指頁表的始地址。32 位虛擬地址的第 1 個子位段共 10 位,其值的范圍從 0 到 1023,對應(yīng)于頁目錄的一個入口點。頁目錄(PTE)的每一個入口點的值為此表項所指的一頁框(page frame) ,32 位虛擬地址的第 2 個子位段共 10 位,其值的范圍從 0 到 1023。頁框(page frame)并不是物理頁,它指是虛存
12、的一個地址空間。3、頁表項的格式、頁表項的格式Linux 中頁表每一個表項的格式,如圖所示: 31 12 11 7 6 5 4 3 2 1 0 Address Reserved DA U RP SW圖 3 頁表項格式其中,各位段的含義如下:P:存在位,表示該表項對地址的轉(zhuǎn)換是否有效。i386 處理器在 P=0 時不解釋表項中的任何位,此時這些位的含義完全由軟件自行解釋。P 位提供了至關(guān)重要的屬性,以支持分頁機制。如果 P=1,則表示虛擬地址所對應(yīng)的頁框存在于物理內(nèi)存中,訪問該虛擬地址的程序可以正常運行;P=0,則表示虛擬地址所對應(yīng)的頁框不存在于物理內(nèi)存中,訪問該虛擬地址的程序?qū)l(fā)頁訪問異常
13、,產(chǎn)生缺頁中斷。使得 Operating System 可以把缺少的頁從磁盤上讀入內(nèi)存,并將讀入頁存入到表項中,然后將該頁標志為存在,再使引起異常的程序繼續(xù)執(zhí)行。R/W :讀寫位,表示對該表項指向的頁可以進行讀、寫或執(zhí)行操作。R/W=1 則該頁可寫,可讀,且可執(zhí)行;R/W=0 則該頁可讀,可執(zhí)行,但不可寫。當處理器7 / 29 文檔可自由編輯打印處于特權(quán)級 02 時,R/W 位被忽略。如該表項位于頁目錄中,則作用于該表項映射的所有各頁。U/S:用戶/系統(tǒng)位。U/S=1 則該頁可在任何處理器特權(quán)級下訪問;U/S=0 則該頁只能在處理器特權(quán)級 02 下被訪問。如該表項位于頁目錄中,則作用于該表項映
14、射的所有各頁。D:已寫標志位。在對該表項映射的頁進行寫訪問之前,處理器對該位置 1。如該表項是頁目錄中表項,處理器不修改 D 位。Address:頁框物理地址的高 20 位。系統(tǒng)將物理內(nèi)存分割成 4K 大小的內(nèi)存頁框,Address 實際上代表了頁框的幀號。4、動態(tài)地址映射、動態(tài)地址映射Linus 虛存采用動態(tài)地址映射方式,即 Process 的地址空間和存儲空間的對應(yīng)關(guān)系是在程序的執(zhí)行過程中實現(xiàn)的:Process 每用到一個地址時, 都需虛存的地址轉(zhuǎn)換機構(gòu)把虛擬地址轉(zhuǎn)化為內(nèi)存的實際地址。其地址映射如下圖所示:圖 4 32 位虛擬地址轉(zhuǎn)換圖動態(tài)地址映射使 Linux 可以實現(xiàn) Process
15、在主存中的動態(tài)重定位,虛存段的動態(tài)擴展和8 / 29 文檔可自由編輯打印移動;也為虛存的實現(xiàn)提供了基礎(chǔ)。5、用戶進程的虛擬內(nèi)存結(jié)構(gòu)、用戶進程的虛擬內(nèi)存結(jié)構(gòu)用戶進程的虛擬內(nèi)存結(jié)構(gòu)如圖所示:9 / 29 文檔可自由編輯打印mm_struct每一個進程的 task_struct 中都有一個結(jié)構(gòu) mm_struct,此結(jié)構(gòu)包含了進程中與儲存管理相關(guān)的大部分信息,其申明如下:struct mm_struct int count;/ 使用該 mm 結(jié)構(gòu)的個數(shù),如果是多處理機,則有可能 count 1pgd_t * pgd; /* 進程頁目錄的起始地址,如上圖所示 */unsigned long conte
16、xt;unsigned long start_code, end_code, start_data, end_data;/*start_code、end_code:進程代碼段的起始地址和結(jié)束地址。start_data、end_data:進程數(shù)據(jù)段的起始地址和結(jié)束地址。*/unsigned long start_brk, brk, start_stack, start_mmap;unsigned long arg_start, arg_end, env_start, env_end;/* arg_start、arg_end:調(diào)用參數(shù)區(qū)的起始地址和結(jié)束地址。env_start、env_end:進程
17、環(huán)境區(qū)的起始地址和結(jié)束地址。*/unsigned long rss, total_vm, locked_vm;/* rss:進程內(nèi)容駐留在物理內(nèi)存的頁面總數(shù)。*/unsigned long def_flags;struct vm_area_struct * mmap; /* 以雙向鏈表組成的 vma 模塊的首指針。 */struct vm_area_struct * mmap_avl; /* 以 avl 樹結(jié)構(gòu)組成的虛擬空間的首指針。*/struct semaphore mmap_sem;用戶進程虛存管理的數(shù)據(jù)結(jié)構(gòu)如圖 5 所示。用戶共有 4GB 的虛存空間,實際可申請的虛存空間為 03GB。
18、3GB4GB 的虛存空間在用戶進程創(chuàng)建時,已由函數(shù) fork()將 kernel的代碼段和數(shù)據(jù)段映射到 3GB4GB 的虛存空間。因而所有進程的 3GB4GB 的虛存空間的映象都是相同的,從而以這種方式使所有進程共享 kernel 的代碼段和數(shù)據(jù)段。VMA進程的虛擬空間通常由一個個 vma 塊組成,這些塊的結(jié)構(gòu)如下所示:struct vm_area_struct struct mm_struct * vm_mm;/* VM area parameters */unsigned long vm_start; /該 vma 塊代表的使用虛擬空間的起始地址unsigned long vm_end;
19、/該 vma 塊代表的使用虛擬空間的結(jié)束地址pgprot_t vm_page_prot; /保護位 unsigned short vm_flags; /標志位/* AVL tree of VM areas per task, sorted by address */short vm_avl_height; /avl 樹高度struct vm_area_struct * vm_avl_left; /vma 塊的左子節(jié)點struct vm_area_struct * vm_avl_right; /vma 塊的右子節(jié)點/* linked list of VM areas per task, sort
20、ed by address */struct vm_area_struct * vm_next; /* 在按地址大小排列的單向鏈表上的下一個指針*/10 / 29 文檔可自由編輯打印/* for areas with inode, the circular list inode-i_mmap */* for shm areas, the circular list of attaches */* otherwise unused */struct vm_area_struct * vm_next_share;struct vm_area_struct * vm_prev_share;/* mo
21、re */struct vm_operations_struct * vm_ops;/對 VMA 塊進行操作的函數(shù)集unsigned long vm_offset;struct inode * vm_inode;/該 VMA 塊對應(yīng)的文件unsigned long vm_pte;/* shared mem */;采用 avl 樹的優(yōu)點是可以快速找到相關(guān)地址所在的 vma 塊。同時,同一個任務(wù)的 vma塊還按前后順序排成一個線性鏈表。6、我們的工作、我們的工作針對上圖所示的用戶進程虛存管理的數(shù)據(jù)結(jié)構(gòu),圍繞它的建立、維護、使用和拆除,我們組作了相應(yīng)的工作,主要包括以下幾點:1、進程的載入、創(chuàng)建及內(nèi)
22、存管理數(shù)據(jù)結(jié)構(gòu)和鏈結(jié)關(guān)系的建立 (sys_execve, sys_fork, sys_clone)2、頁表的建立與釋放 ( new_page_tables, free_page_tables, .)3、虛擬內(nèi)存的申請與釋放(sys_mmap, sys_munmap)4、缺頁中斷處理(do_page_fault)5、虛擬塊 VMA 的管理(sys_remap, sys_mprotect)6、 數(shù)據(jù)結(jié)構(gòu)及鏈結(jié)關(guān)系的拆除(sys_exit)其中,虛擬內(nèi)存的申請與釋放由林濤和徐玫峰同學(xué)負責,虛擬塊 VMA 的管理由范昭偉同學(xué)負責,相關(guān)的工作體現(xiàn)在他們的分析報告中。11 / 29 文檔可自由編輯打印第四
23、章第四章 Process 的虛存管理數(shù)據(jù)結(jié)構(gòu)的建立、維護、的虛存管理數(shù)據(jù)結(jié)構(gòu)的建立、維護、拆除及相關(guān)系統(tǒng)調(diào)用流程拆除及相關(guān)系統(tǒng)調(diào)用流程1、進程的載入、創(chuàng)建及內(nèi)存管理數(shù)據(jù)結(jié)構(gòu)和鏈結(jié)關(guān)系的建立、進程的載入、創(chuàng)建及內(nèi)存管理數(shù)據(jù)結(jié)構(gòu)和鏈結(jié)關(guān)系的建立sys_execve 系統(tǒng)調(diào)用負責將可執(zhí)行文件映象載入到內(nèi)存,與內(nèi)存相關(guān)的操作主要是: 通過調(diào)用 exit_mmap 清除當前進程的所有的虛存塊,通過調(diào)用 clear_page_table 清除當前進程的頁表項,通過調(diào)用 flush_old_signals 清除當前進程的殘留信號,通過調(diào)用flush_old_files 清除當前進程的已打開文件,從而將當前進
24、程掏空,成為一個空殼。然后系統(tǒng)根據(jù) bprm 結(jié)構(gòu)更新 current 進程的控制塊,并通過調(diào)用兩次 do_mmap 分別將執(zhí)行文件的代碼段和數(shù)據(jù)段映射到虛存。系統(tǒng)一般只將前兩頁載入物理內(nèi)存中,同時分配一頁給堆棧,其它的均留在硬盤中通過虛擬內(nèi)存映射機制映射為虛擬內(nèi)存。當運行中發(fā)生缺頁中斷時,系統(tǒng)處理缺頁中斷,將缺頁調(diào)入物理內(nèi)存中,如果發(fā)生物理內(nèi)存不足的情況,則由kswapd()選擇合適的頁調(diào)入交換文件中或扔掉(如未發(fā)生寫操作) 。具體流程如下:asmlinkage int sys_execve(struct pt_regs regs)/為 do_execve()的調(diào)用準備參數(shù)do_execve
25、()初始化 bprm /* bprm 是 struct linux_binprm,進程控制塊中某些參數(shù)的暫存器*/search_binary_handler()/*尋找二進制文件的處理程序(handler),并用該 handler(一般是 load_aout_binary)程序處理該二進制文件*/load_aout_binary()do_load_aout_binary()/異常情況判斷,flush_old_exec(bprm)exec_mmap()/ if necessary, then copy_on_writeexit_mmap(current-mm)/清除當前進程的所有的虛存塊12 /
26、 29 文檔可自由編輯打印clear_page_table(current)/清除當前進程的頁表項flush_tlb_mm(current-mm); /?flush_thread(); /?flush_old_signals(current-sig);/清除當前進程的殘留信號flush_old_files(current-files);/清除當前進程的已打開文件/到此為止,當前進程已被掏空,成為一個空殼。根據(jù) bprm 結(jié)構(gòu)更新 current 進程的控制塊do_mmap();/將執(zhí)行文件的代碼段映射到虛存do_mmap();/將執(zhí)行文件的數(shù)據(jù)段映射到虛存 / do_load_aout_bin
27、ary /end for load_aout_binary/ end for search_binary_handler/end for do_execve/end for sys_execve2、do_fork()當通過 sys_fork 和 sys_clone 系統(tǒng)調(diào)用來創(chuàng)建子進程時,系統(tǒng)將通過 do_fork 函數(shù)來完成大部分的創(chuàng)建任務(wù),do_fork 函數(shù)首先申請一頁的核心空間給進程控制塊,再申請一頁的核心空間給系統(tǒng)堆棧,再通過 copy_mm 函數(shù)為子進程復(fù)制父進程的虛擬空間(如果是sys_clone 系統(tǒng)調(diào)用,則不用復(fù)制,子進程的 mm 指針指向父進程 mm_struct) ,具體
28、流程如下:asmlinkage int sys_fork(struct pt_regs regs)return do_fork(SIGCHLD, regs.esp, ®s);asmlinkage int sys_clone(struct pt_regs regs)unsigned long clone_flags;unsigned long newsp;clone_flags = regs.ebx;newsp = regs.ecx;if (!newsp)newsp = regs.esp;return do_fork(clone_flags, newsp, ®s);d
29、o_fork()申請一頁的核心空間給進程控制塊 (struct task_struct *p)申請一頁的核心空間給系統(tǒng)堆棧*P=*current;/復(fù)制父進程的進程控制塊作必要的修改13 / 29 文檔可自由編輯打印copy_mm()如果是 clone父子進程的 mm 指針指向同一個 mm_struct;mm_struct-count+;else /畫圖struct mm_struct *mm = 申請一頁核心空間;*mm = *current-mm; /復(fù)制父進程的相關(guān)信息new_page_tables(); /建立新的頁目錄表 pgd,且復(fù)制 init 進程的 768-1023 項dup_
30、mmap();/復(fù)制父進程的虛擬空間映射for 對于父進程中的每一個 VMA 塊復(fù)制該 VMA 塊,作相應(yīng)修改并重新鏈起來;copy_page_range(mm, current-mm, 該 VMA 塊)其工作機制是循環(huán)調(diào)用 copy_pmd_range,將 vma 塊中的所有虛擬空間復(fù)制到對應(yīng)的虛擬空間中。在做復(fù)制之前,必須確保新任務(wù)對應(yīng)的被復(fù)制的虛擬空間中必須都為零。 /end for dup_mmap()/ end for copy_mm(). ./end for do_fork()2、數(shù)據(jù)結(jié)構(gòu)及鏈結(jié)關(guān)系的拆除(、數(shù)據(jù)結(jié)構(gòu)及鏈結(jié)關(guān)系的拆除(sys_exit)sys_exit()系統(tǒng)調(diào)用
31、sys_exit 來結(jié)束進程,調(diào)用 exit_mm()將所有虛擬內(nèi)存都結(jié)束掉,最后中止進程。asmlinkage int sys_exit(int error_code) ()do_exit(). .kerneld_exit();_exit_mm(current);if ( !-current-mm-count ) /無其他進程共享該 mm_structexit_mmap(mm);14 / 29 文檔可自由編輯打印for 對于當前進程 current-mm 中的每一個 VMA 塊,調(diào)用 vm_ops-unmap 釋放該 VMA 塊對應(yīng)的虛擬空間調(diào)用 zap_page_range 將指向釋放掉的
32、虛擬空間中的 pte 頁表項清零。調(diào)用 kfree 釋放該 VMA 塊結(jié)構(gòu)占用的物理空間。free_page_tables(mm);/將 mm-pdg 中所有的 pte 頁表項清空,并將 mm-pdg 清空kfree(mm);current-mm = init.mm/end for _exit_mm(current);_exit_files(current);_exit_fs(current);_exit_sighand(current);/end for do_exit;3、缺頁中斷服務(wù)、缺頁中斷服務(wù)當程序在運行中,訪問到的無效的虛擬地址的時候,系統(tǒng)將激發(fā)出缺頁中斷。激發(fā)缺頁中斷的情況通常有
33、四種:1.COW 型中斷,當某個進程進行寫操作時,如果寫的頁是多進程在使用時,為了不影響其它進程的正常運行,通常需要將該頁復(fù)制一份,供執(zhí)行寫操作的進程單獨使用。2.被訪問的物理頁由于太長時間沒有訪問而被 kswapd 置換到 s 中。3.被訪問的物理頁由于是第一次訪問,所以還在磁盤上或由于訪問后被置換時因為沒有發(fā)生寫操作,而未寫到 s 中。4.當進程動態(tài)的訪問一片存儲區(qū)域時,如在程序中動態(tài)開辟的數(shù)組等,則該頁不在 s 中,也不在磁盤上。缺頁中斷服務(wù)入口程序是函數(shù) do_page_faultdo_page_fault 首先進行各種錯誤情況判斷,并作相應(yīng)處理,然后根據(jù) error_code 來判斷
34、缺頁中斷類型:第一種情況采用 do_wp_page 函數(shù)來處理,第二、三、四種情況由do_no_page 函數(shù)來處理。下面將分別介紹這些函數(shù)的流程圖。void do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma,unsigned long address, int write_access)15 / 29 文檔可自由編輯打印為復(fù)制可寫頁申請一頁空間根據(jù) address 計算pgd ,pmd,pte退出使用該物理頁的進程1 ?將該物理頁置dirty釋放原先分配的復(fù)制頁將物理頁復(fù)制到復(fù)制頁上將復(fù)制頁鏈入虛存中將指向原先物
35、理頁的 pte 釋放掉退出異常11圖 7 do_wp_page 示意圖void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,unsigned long address, int write_access)根據(jù) address 計算三級頁表中 pgd/pmd/pte 的值,如無對應(yīng)的項,分配空間將其填上if ( pte_present(entry) )該頁已在內(nèi)存中,return;/可能是共享該頁的其他進程已將該頁讀入else if (!pte_none(entry)/情況 2pte 中該項非空,說明該頁被 k
36、swapd 置換到 s 中,調(diào)用 do_s 讀入該頁;else if ( !vma-vm_ops | !vma-vm_ops-nopage)/情況 4該頁對應(yīng)的 VMA 塊沒有相應(yīng)的 nopage 操作,說明該 VMA 塊對應(yīng)的是數(shù)據(jù)段內(nèi)容調(diào)用_get_free_page 操作為該頁分配內(nèi)存,并將該頁賦值為 0,同時鏈入該進程的頁表中else/情況 3調(diào)用虛擬塊操作將磁盤中對應(yīng)文件讀入 page 中,將 pte 表中對應(yīng)的項指向該頁。將該頁 dirty 位置位,如果該頁有多進程使用,且非共享,置寫保護位。16 / 29 文檔可自由編輯打印第五章第五章 主要函數(shù)分析主要函數(shù)分析Memory.c在
37、該文件中,Linux 提供了對虛擬內(nèi)存操作的若干函數(shù),其中包括對虛擬頁的復(fù)制、新建頁表、清除頁表、處理缺頁中斷等等。1static inline void copy_page(unsigned long from, unsigned long to)為了節(jié)約內(nèi)存的使用,在系統(tǒng)中,各進程通常采用共享內(nèi)存,即不同的進程可以共享同一段代碼段或數(shù)據(jù)段。當某一進程發(fā)生對共享的內(nèi)存發(fā)生寫操作時,為了不影響其它進程的正常運行,系統(tǒng)將把該內(nèi)存塊復(fù)制一份,供需要寫操作的進程使用,這就是所謂的copy-on-write 機制。copy_page 就是提供復(fù)制內(nèi)存功能的函數(shù),它調(diào)用 C 語言中標準的內(nèi)存操作函數(shù),將
38、首地址為 from 的一塊虛擬內(nèi)存頁復(fù)制到首地址為 to 的空間中。2、void clear_page_tables(struct task_struct * tsk)clear_page_table 的功能是將傳入的結(jié)構(gòu) tsk 中的 pgd 頁表中的所有項都清零,同時將二級頁表所占的空間都釋放掉。傳入 clear_page_tables 的是當前進程的 tsk 結(jié)構(gòu),取得該進程的一級頁目錄指針 pgd 后,采用循環(huán)的方式,調(diào)用 free_one_pgd 清除 pgd 表。表共 1024項。在 free_one_pgd 中,實際執(zhí)行的功能只調(diào)用一次 free_one_pmd(在 80 x86
39、 中,由于硬件的限制,只有兩級地址映射,故將 pmd 與 pgd 合并在一起) 。在 free_one_pmd 中,函數(shù)調(diào)用 pte_free 將對應(yīng)于 pmd 的二級頁表所占的物理空間釋放掉(進程代碼、數(shù)據(jù)所用的物理內(nèi)存在 do_munmap 釋放掉了)并將 pmd 賦值為零。clear_page_table 在系統(tǒng)啟動一個可執(zhí)行文件的映象或載入一個動態(tài)鏈接庫時被調(diào)用。在 fs/exec.c 中的 do_load_elf_binary()或 do_load_aout_binary()調(diào)用 flash_old_exec,后者調(diào)用 exec_mmap,而 exec_mmap 調(diào)用 clear_p
40、age_table。其主要功能是當啟動一個新的應(yīng)用程序的時候,將復(fù)制的 mm_struct 中的頁表清除干凈,并釋放掉原有的所有二級頁表空間。3、void oom(struct task_struct * task)返回出錯信息。4、void free_page_tables(struct mm_struct * mm) 17 / 29 文檔可自由編輯打印在 free_page_table 中,大部分的代碼與 clear_page_table 中的函數(shù)一致。所不同的是,該函數(shù)在最后調(diào)用了 pgd_free(page_dir),即不光釋放掉二級頁表所占的空間,同時還釋放一級頁目錄所占的空間。這是
41、因為 free_page_tables 被_exit_mm 調(diào)用,_exit_mm 又被do_exit (kernel/kernel.c)調(diào)用。當進程中止、系統(tǒng)退出或系統(tǒng)重起時都需要用do_exit(屬于進程管理)將所有的進程結(jié)束掉。在結(jié)束進程過程中 ,將調(diào)用free_page_table 將進程的空間全部釋放掉,當然包括釋放進程一級頁目錄所占的空間。5、int new_page_tables(struct task_struct * tsk)該函數(shù)的主要功能是建立新的頁目錄表,它的主要流程如如下:1.調(diào)用 pgd_alloc()為新的頁目錄表申請一片 4K 空間 。2.將初始化進程的內(nèi)存結(jié)構(gòu)
42、中從 768 項開始到 1023 項的內(nèi)容復(fù)制給新的頁表(所有的進程都共用虛擬空間中 3G4G 的內(nèi)存,即在核心態(tài)時可以訪問所有相同的存儲空間) 。3.調(diào)用宏 SET_PAGE_DIR(include/asm/pgtable.h)將進程控制塊 tsk-ts-CR3 的值改為新的頁目錄表的首地址,同時將 CPU 中的 CR3 寄存器的值改為新的頁目錄表的首地址,從而使新進程進入自己的運行空間。4.將 tsk-mm-pgd 改為新的頁目錄表的首地址。new_page_tables 被 copy_mm 調(diào)用,而 copy_mm 被 copy_mm_do_fork 調(diào)用,這兩個函數(shù)都在 kernel/
43、fork.c 中。同時,new_page_tables 也可以在 exec_mmap(fs/exec.c)中調(diào)用。即新的進程的產(chǎn)生可以通過兩種途徑,一種是 fork,在程序中動態(tài)地生成新的進程,這樣新進程的頁表原始信息利用 copy_mm 從其父進程中繼承而得,另一種是運行一個可執(zhí)行文件映象,通過文件系統(tǒng)中的 exec.c,將映象復(fù)制到 tsk 結(jié)構(gòu)中。兩種方法都需要調(diào)用new_page_tables 為新進程分配頁目錄表。6、static inline void copy_one_pte(pte_t * old_pte, pte_t * new_pte, int cow)將原 pte 頁表項
44、復(fù)制到 new_pte 上,其流程如下:1.檢測 old_pte 是否在內(nèi)存中,如不在物理內(nèi)存中,調(diào)用 s 按 old_pte 在 s 中的入口地址,將 old_pte 復(fù)制到內(nèi)存中,同時把 old_pte 的入口地址賦給 new_pte 并返回。反之轉(zhuǎn)向 3。2.獲取 old_pte 對應(yīng)的物理地址的頁號。18 / 29 文檔可自由編輯打印3.根據(jù)頁號判斷 old_pte 是否為系統(tǒng)保留的,如果為系統(tǒng)保留的,這些頁為所有的進程在核心態(tài)下使用,用戶進程沒有寫的權(quán)利,則只需將 old_pte 指針直接轉(zhuǎn)賦給 new_pte 后返回。反之則該 pte 屬于普通內(nèi)存的,則轉(zhuǎn)向 4。4.根據(jù)傳入的 C
45、-O-W 標志,為 old_pte 置寫保護標志,如果該頁是從 s 中得來的,將 old_pte 頁置上“dirty”標志。將 old_pte 賦值給 new_pte。5.將 mem_map 結(jié)構(gòu)中關(guān)于物理內(nèi)存使用進程的個數(shù)的數(shù)值 count 加 1。7、static inline int copy_pte_range(pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long address, unsigned long size, int cow)通過循環(huán)調(diào)用 copy_one_pte 將從源 src_pmd 中以地址 address 開始的長度為 size
46、 的空間復(fù)制給 dst_pmd 中。如 dst_pmd 中還未分配地址為 address 的頁表項,則先給三級頁表pte 表分配 4K 空間。 (每調(diào)用一次 copy_one_pte 復(fù)制 4K 空間。在一次 copy_pte_range 中最多可復(fù)制 4M 空間) 。8、static inline int copy_pmd_range(pgd_t *dst_pgd, pgd_t *src_pgd, unsigned long address, unsigned long size, int cow)通過循環(huán)調(diào)用 copy_pte_range 將從源 src_pgd 中以地址 address
47、開始的長度為 size 的空間復(fù)制給 dst_pgd 中。如 dst_pgd 中還未分配地址為 address 的頁表項,則在一級(同時也是二級)頁表中給對應(yīng)的 pmd 分配目錄項。9、int copy_page_range(struct mm_struct *dst, struct mm_struct *src,struct vm_area_struct *vma)該函數(shù)的主要功能是將某個任務(wù)或進程的 vma 塊復(fù)制給另一個任務(wù)或進程。其工作機制是循環(huán)調(diào)用 copy_pmd_range,將 vma 塊中的所有虛擬空間復(fù)制到對應(yīng)的虛擬空間中。在做復(fù)制之前,必須確保新任務(wù)對應(yīng)的被復(fù)制的虛擬空間中
48、必須都為零。copy_page_range按 dup_mmap()-copy_mm()-do_fork()的順序被調(diào)用(以上三個函數(shù)均在 kernel/fork.c 中) 。當進程被創(chuàng)建的時候,需要從父進程處復(fù)制所有的虛擬空間,copy_page_range 完成的就是這個任務(wù)。copy_page_range 的函數(shù)調(diào)用關(guān)系見圖 8。19 / 29 文檔可自由編輯打印copy_page_rangecopy_pmd_rangecopy_pte_rangecopy_one_ptedup_mmapcopy_mmdo_forkkernel/fork.c圖 8 copy_page_range 示意圖9、
49、static inline void free_pte(pte_t page)虛存頁 page 如在內(nèi)存中,且不為系統(tǒng)的保留內(nèi)存,調(diào)用 free_page 將其釋放掉(如在系統(tǒng)保留區(qū)中,則為全系統(tǒng)共享,故不能刪除) 。如 page 在 s 中,調(diào)用 s()將其釋放。10、static inline void forget_pte(pte_t page)如 page 不為空,調(diào)用 free_pte 將其釋放。11、static inline void zap_pte_range(pmd_t * pmd, unsigned long address, unsigned long size)zap
50、為 zero all pages 的縮寫。該函數(shù)的作用是將在 pmd 中從虛擬地址 address 開始,長度為 size 的內(nèi)存塊通過循環(huán)調(diào)用 pte_clear 將其頁表項清零,調(diào)用 free_pte 將所含空間中的物理內(nèi)存或交換空間中的虛存頁釋放掉。在釋放之前,必須檢查從 address 開始長度為size 的內(nèi)存塊有無越過 PMD_SIZE.(溢出則可使指針逃出 01023 的區(qū)間)。12、static inline void zap_pmd_range(pgd_t * dir, unsigned long address, unsigned long size)函數(shù)結(jié)構(gòu)與 zap_p
51、te_range 類似,通過調(diào)用 zap_pte_range 完成對所有落在 address 到address+size 區(qū)間中的所有 pte 的清零工作。zap_pmd_range 至多清除 4M 空間的物理內(nèi)存。13、int zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)20 / 29 文檔可自由編輯打印函數(shù)結(jié)構(gòu)與前兩個函數(shù)類似。將任務(wù)從 address 開始到 address+size 長度內(nèi)的所有對應(yīng)的 pmd 都清零。zap_page_range 的調(diào)用關(guān)系與被調(diào)用的關(guān)系如
52、圖 9 可知。zap_page_range的主要功能是在進行內(nèi)存收縮、釋放內(nèi)存、退出虛存映射或移動頁表的過程中,將不在使用的物理內(nèi)存從進程的三級頁表中清除。 (在討論 clear_page_tables 時,就提到過當進程退出時,釋放頁表之前,先保證將頁表對應(yīng)項清零,保證在處于退出狀態(tài)時,進程不占用03G 的空間。 )zap_page_rangevm_truncatedo_munmapexit_mmapmove_page_tableszap_pmd_rangezap_pte_rangefree_page圖 9 zap_page_range 調(diào)用關(guān)系示意圖14、static inline voi
53、d zeromap_pte_range(pte_t * pte, unsigned long address, unsigned long size, pte_t zero_pte)15、static inline int zeromap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size, pte_t zero_pte)16、int zeromap_page_range(unsigned long address, unsigned long size, pgprot_t prot)這三個函數(shù)與前面的三個函數(shù)從結(jié)構(gòu)
54、上看很相似,他們的功能是將虛擬空間中從地址address 開始,長度為 size 的內(nèi)存塊所對應(yīng)的物理內(nèi)存都釋放掉,同時將指向這些區(qū)域的pte 都指向系統(tǒng)中專門開出的長度為 4K,全為 0 的物理頁。zeromap_page_range 在 kernel代碼中沒有被引用,這個函數(shù)是舊版本的 Linux 遺留下來的,在新版本中已經(jīng)被zap_page_range 所替代。17、static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,unsigned long offset,
55、pgprot_t prot)18、static inline int remap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size,unsigned long offset, pgprot_t prot)19、int remap_page_range(unsigned long from, unsigned long offset, unsigned long size, 21 / 29 文檔可自由編輯打印pgprot_t prot)這三個函數(shù)也同前面的函數(shù)一樣,層層調(diào)用,現(xiàn)僅介紹一下最后一個函數(shù)的作用。remap
56、_page_range 的功能是將原先被映射到虛擬內(nèi)存地址 from 處的,大小為 size 的虛擬內(nèi)存塊映射到以偏移量 offset 為起始地址的虛擬內(nèi)存中,同時將原來的 pte、pmd 項都清零。該函數(shù)也是逐級調(diào)用,在 remap_pte_range 中,通過 set_pte 將的物理頁映射到新的虛擬內(nèi)存頁表項 pte 上。remap_page_range 函數(shù)的功能與下文中的 remap.c 中介紹的功能相近,因此在 kernel 中也沒有用到。20、unsigned long put_dirty_page(struct task_struct * tsk, unsigned long
57、page,unsigned long address)將虛擬內(nèi)存頁 page 鏈接到任務(wù) tsk 中虛擬地址為 address 的虛擬內(nèi)存中,其主要調(diào)用的流程如下:put_dirty_page-setup_arg_page-do_load_xxx_binary(xxx 為 aout 或 elf,這些函數(shù)都在 fsexec.c 中),它的功能是將在載入可執(zhí)行文件的時候,將其相關(guān)的堆棧信息、環(huán)境變量等復(fù)制到當前進程的空間上。21、void handle_mm_fault(struct vm_area_struct * vma, unsigned long address, int write_ac
58、cess)用于處理 ALPHA 機中的缺頁中斷22 / 29 文檔可自由編輯打印mmap.c在 mmap.c 中,主要提供了對進程內(nèi)存管理進行支持的函數(shù),主要包括了do_mmap、do_munmap 等對進程的虛擬塊堆 avl 數(shù)進行管理的函數(shù)。圖 10 mmap.c 中函數(shù)調(diào)用圖有關(guān)有關(guān) avl 樹的一些操作:樹的一些操作:1、static inline void avl_neighbours (struct vm_area_struct * node, struct vm_area_struct * tree, struct vm_area_struct * to_the_left, st
59、ruct vm_area_struct * to_the_right)尋找 avl 樹 tree 中的節(jié)點 node 的前序節(jié)點和后序節(jié)點,將結(jié)果放在指針 to_the_left 和to_the_right 中,即使得*to_the_left-next=node,node-next=*to_the_right。在實際搜索中,過程是找到 node 節(jié)點中的左節(jié)點的最右節(jié)點和右節(jié)點的最左節(jié)點,采用 avl 樹搜索可以提高效率。2、static inline void avl_rebalance (struct vm_area_struct * nodeplaces_ptr, int count)將
60、由于插入操作或刪除操作而造成不平衡的 avl 樹恢復(fù)成平衡狀態(tài)。nodeplaces_ptr 是指向的是需要調(diào)整的子樹的根節(jié)點,count 是該子樹的高度。3、 static inline void avl_insert (struct vm_area_struct * new_node, struct vm_area_struct * ptree)將新節(jié)點 new_node 插入 avl 樹 ptree 中,并將該樹重新生成平衡 avl 樹。在創(chuàng)建 avl 樹時,將 vma 模塊不斷的插入 avl 樹中,構(gòu)建一個大的 avl 樹。當進程創(chuàng)建時,復(fù)制父進程后需要將以雙向鏈表拷貝過來的 vma 鏈生成 avl
溫馨提示
- 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 關(guān)于住房合同范例
- 勞務(wù)內(nèi)部合同范本
- 農(nóng)村養(yǎng)殖用地合同范例
- 豐田購車合同范本
- 企業(yè)招商加盟合同范本
- 俱樂部股東協(xié)議合同范本
- 關(guān)于醫(yī)療服務(wù)項目合同范本
- 增強現(xiàn)實(AR)與虛擬現(xiàn)實(VR)應(yīng)用開發(fā)考核試卷
- 2025-2030年地下空間礦產(chǎn)勘查行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報告
- 2025-2030年手工銅藝雕塑行業(yè)跨境出海戰(zhàn)略研究報告
- 周口2024年河南周口市公安機關(guān)招聘輔警458人筆試歷年參考題庫附帶答案詳解
- 《頭面部穴位按摩》課件
- 2024美團簡化版商家合作合同標準文本一
- 2025年貴州黔源電力股份有限公司招聘筆試參考題庫含答案解析
- 《休閑食品加工技術(shù)》 課件 1 休閑食品生產(chǎn)與職業(yè)生活
- 春季開學(xué)安全第一課
- 《病史采集》課件
- 十大護理安全隱患
- 2025年新生兒黃疸診斷與治療研究進展
- 廣東大灣區(qū)2024-2025學(xué)年度高一上學(xué)期期末統(tǒng)一測試英語試題(無答案)
- 失效模式和效應(yīng)分析護理
評論
0/150
提交評論