版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、嵌入式Linux內核體系(tx)架構李超lichao一百六十九頁內存(ni cn)管理Linux的內存(ni cn)管理 進程的用戶空間管理請頁機制物理內存的管理、分配與回收交換機制內存管理示例共一百六十九頁PART 4.1 linux內存(ni cn)管理共一百六十九頁內存(ni cn)管理內存管理是一個操作系統(tǒng)必不可少,并且非常重要的一環(huán)。Linux的成功和它優(yōu)秀的內存管理聯(lián)系非常密切,因為一個系統(tǒng)的高效性欲穩(wěn)定性往往決定于它的內存管理機制。對每個程序員來說.他們都希望有無窮大的快速的內存,然而,現(xiàn)階段是不可能的。為了解決無窮大,Linux 引入了虛擬存儲系統(tǒng);為
2、了解決快速,Linux 引入了cache、交換(jiohun)機制等等,以使的存儲系統(tǒng),在容量上接近硬盤,在速度上接近cache。共一百六十九頁內存(ni cn)的層次結構 每個程序員都喜歡無窮大、快速的存儲器,同時又希望它是廉價的。但不幸的是,當前技術沒有能夠提供這樣的存儲器,大部分的計算機都有一個存儲器層次結構:即少量(sholing)的非??焖?、昂貴、易變的高速緩存(cache);若干兆字節(jié)的中等速度、中等價格、易變的主存儲器(RAM);數(shù)百兆或數(shù)千兆的低速、廉價、不易變的磁盤。 這些資源的合理使用與否直接關系著系統(tǒng)的效率。 共一百六十九頁內存(ni cn)管理地址映射機制,就是在虛擬內
3、存與物理內存上的一個橋梁。要做的事情可能(knng)就是通過幾個不同的表,把虛擬地址轉換成物理地址,把物理地址轉化虛擬地址。共一百六十九頁虛擬內存的基本(jbn)思想:在計算機中運行的程序,其代碼、數(shù)據(jù)和堆棧的總量可以超過實際內存的大小,操作系統(tǒng)只將當前使用的程序塊保留在內存中,其余的程序塊則保留在磁盤上。必要時,操作系統(tǒng)負責在磁盤和內存之間交換程序塊。擴大(kud)了的記憶虛擬內存共一百六十九頁虛擬內存、內核空間(kngjin)和用戶空間(kngjin)內核(ni h)空間(1GB)進程1的用戶空間(3GB)進程2的用戶空間(3GB)進程n的用戶空間(3GB)虛擬地址空間0 x0000000
4、00 xBFFFFFFF0 xC00000000 xFFFFFFFF每個進程通過系統(tǒng)調用進入內核,Linux內核空間由系統(tǒng)內的所有進程共享。從進程的角度來看,每個進程擁有4GB的虛擬地址空間(也叫虛擬內存)。每個進程有各自的私有用戶空間(0-3G),這個空間對系統(tǒng)中的其他進程是不可見的。最高的1GB內核空間則為所有進程以及內核所共享。 共一百六十九頁虛擬內存共4G字節(jié)(z ji),分為兩部分:內核空間(最高的1G字節(jié))用戶空間(較低的3G字節(jié))每個進程最大擁有3G字節(jié)私有虛存空間地址轉換通過頁表把虛存空間的一個地址轉換為物理空間中的實際地址。虛擬內存、內核(ni h)空間和用戶空間共一百六十九
5、頁任意一個時刻,在一個CPU上只有一個進程在運行。所有對于此CPU來講,在這個時刻,整個系統(tǒng)(xtng)只存在一個4GB的虛擬地址空間。盡管每個進程都可以有4GB的虛擬地址空間,但是在CPU眼里,只有一個虛擬地址空間存在當進程發(fā)生切換,頁表也將更換為相應進程的頁表,這就可以使每個進程都有自己的虛擬地址空間而互不影響。所以,在任意時刻,對于一個CPU來說,只需有當前進程的頁表,就可以實現(xiàn)虛擬地址到物理地址的轉換虛擬內存、內核空間(kngjin)和用戶空間(kngjin)共一百六十九頁內核空間由所有進程共享,其中存放的是內核代碼和數(shù)據(jù),即“內核映象”(kernel image)進程的用戶空間中存放
6、的是用戶程序的代碼和數(shù)據(jù)內核空間映射到物理(wl)內存總是從最低地址(0 x00000000)開始,使之在內核空間與物理內存之間建立簡單的線性映射關系。內核空間到物理(wl)內存的映射共一百六十九頁03G4G0X虛擬地址空間(kngjin) 物理(wl)內存圖4.1 內核的虛擬地址空間到物理地址空間的映射 內核空間到物理內存的映射物理地址與虛擬地址之間的位移量就是3GB(0 xC0000000) ,在Linux代碼中就叫做PAGE_OFFSET。對于內核空間而言,給定一個虛地址x,其物理地址為“x- PAGE_OFFSET”。這種映射關系只適應于內核空間,而用戶空間的地址映射要復雜得多,它是通
7、過分頁機制完成的。共一百六十九頁Linux虛擬內存的實現(xiàn)需要多種機制(jzh)的支持地址映射機制請頁機制內存分配和回收機制交換機制緩存和刷新機制虛擬內存實現(xiàn)(shxin)機制共一百六十九頁地址映射圖4.2 虛擬內存實現(xiàn)(shxin)機制及之間的關系虛擬內存實現(xiàn)機制(jzh)及之間的關系共一百六十九頁虛擬內存實現(xiàn)(shxin)機制及之間的關系首先內核通過映射機制把進程的虛擬地址映射到物理地址,在進程運行時,如果內核發(fā)現(xiàn)進程要訪問的頁沒有在物理內存時,就發(fā)出了請頁要求;如果有空閑的內存可供分配,就請求分配內存(于是用到了內存的分配和回收),并把正在使用的物理頁記錄在頁緩存中(使用了緩存機制);如果
8、沒有足夠的內存可供分配,那么就調用交換機制,騰出(tn ch)一部分內存;另外在地址映射中要通過TLB(轉換查找緩沖區(qū), Translation Lookaside Buffer) 來尋找物理頁;交換機制中也要用到交換緩存,并且把物理頁內容交換到交換文件中后也要修改頁表來映射文件地址共一百六十九頁內存(ni cn)尋址分頁機制為了減少地址轉換所要求的總線周期數(shù)量,最近存取的頁目錄和頁表會被存放在處理器的緩沖器件中,該緩沖器件被稱為轉換查找緩沖區(qū)TLB ( Transla-tion Lookaside Buffer)。TLB可以(ky)滿是大多數(shù)讀頁目錄和頁表的請求而無需使用總線周期。只有當TL
9、B中不包含要求的頁表項時才會使用額外的總線周期從內存中讀取頁表項,這通常在一個頁表項很長時間沒有存取過時才會出現(xiàn)這種情況共一百六十九頁PART 4.2 用戶(yngh)進程管理共一百六十九頁每個進程(jnchng)經(jīng)編譯、鏈接后形成的二進制映像文件有一個代碼段和數(shù)據(jù)段,其中代碼段在下,數(shù)據(jù)段在上。數(shù)據(jù)段中包含了所有靜態(tài)分配的數(shù)據(jù)空間,即全局變量和所有聲明為static的局部變量,這些空間是進程所必需的,是在建立一個進程的運行映像時就分配好的。進程的用戶空間(kngjin)管理共一百六十九頁由圖可以看出,堆棧段安排在用戶空間的頂部,運行時由頂向下延伸;代碼段和數(shù)據(jù)段則在低部,運行時并不向上(xi
10、ngshng)延伸。從數(shù)據(jù)段的頂部到堆棧段地址的下沿這個區(qū)間是一個巨大的空洞,這就是進程在運行時調用malloc()可以動態(tài)分配的空間,也叫動態(tài)內存或堆。進程的用戶(yngh)空間管理堆棧段空洞數(shù)據(jù)段代碼段進程的用戶空間(3G) 共一百六十九頁每個進程擁有3GB的用戶空間,但其地址都是虛地址,因此用戶進程在這個虛擬內存中并不能真正地運行起來,必須把用戶空間中的虛地址最終映射到物理存儲空間才行,而這種映射的建立和管理是由內核完成的。所謂向內核申請一塊空間,實際上是請求內核分配一塊虛存區(qū)間(q jin)和相應的若干物理頁面,并建立映射關系進程的用戶空間(kngjin)管理共一百六十九頁內核在創(chuàng)建進
11、時并不是為整個用戶空間都分配好相應的物理空間,而是根據(jù)需要才正分配一些物理頁面并建立映射。系統(tǒng)利用了請頁機制避免對物理內存的過分使用。因為進程訪問的用戶空間中的頁可能當前(dngqin)不在物理內存中,這時,操作系統(tǒng)通過請頁機制把數(shù)據(jù)從磁盤裝入到物理內存。為此,系統(tǒng)需要修改進程的頁表,以標志用戶空間中的頁已經(jīng)裝入到物理頁面中。進程的用戶空間(kngjin)管理共一百六十九頁Linux把進程的用戶空間劃分為一個個區(qū)間,便于管理一個進程的用戶地址(dzh)空間主要由mm_struct結構和vm_area_structs結構來描述。mm_struct結構對進程整個用戶空間進行描述vm_area_st
12、ructs結構對用戶空間中各個區(qū)間(簡稱虛存區(qū))進行描述 進程用戶(yngh)空間 共一百六十九頁struct mm_struct atomic_t count; pgd_t * pgd; int map_count; struct semaphore mmap_sem; unsigned long start_code,end_code,start_data,end_data; unsigned long start_brk, brk, start_stack; unsigned long arg_start, arg_end, env_start, env_end; unsigned lo
13、ng rss, total_vm, locked_vm; unsigned long def_flags; struct vm_area_struct *mmap, *mmap_avl, *mmap_cache; unsigned long swap_cnt; unsigned long swap_address; ; mm_struct 結構(jigu) 共一百六十九頁域名說 明count對mm_struct結構的引用進行計數(shù)。為了在Linux中實現(xiàn)線程,內核調用clone派生一個線程,線程和調用進程共享用戶空間(kngjin),即mm_struct結構,派生后系統(tǒng)會累加mm_struct中
14、的引用計數(shù)。pgd進程的頁目錄(ml)基地址,當調度程序調度一個進程運行時,就將這個地址轉成物理地址,并寫入控制寄存器(CR3)map_count在進程的整個用戶空間中虛存區(qū)的個數(shù)semaphore對mm_struct結構進行串行訪問所使用的信號量Start_code,end_code, start_data, end_data進程的代碼段和數(shù)據(jù)段的起始地址和終止地址start_brk, brk, start_stack;每個進程都有一個特殊的地址區(qū)間,這個區(qū)間就是所謂的堆,也就是圖4.4中的空洞。前兩個域分別描述堆的起始地址和終止的地址,最后一個域描述堆棧段的起始地址。arg_start,
15、arg_end, env_start, env_end命令行參數(shù)所在的堆棧部分的起始地址和終止地址;環(huán)境串所在的堆棧部分的起始地址和終止地址rss, total_vm, locked_vm進程貯留在物理內存中的頁面數(shù),進程所需的總頁數(shù),被鎖定在物理內存中的頁數(shù)。mmapvm_area_struct虛存區(qū)結構形成一個單鏈表,其基址由小到大排列mmap_avlvm_area_struct虛存區(qū)結構形成一個顆AVL平衡樹mmap_cache最近一次用到的虛存區(qū)很可能下一次還要用到,因此,把最近用到的虛存區(qū)結構放入高速緩存,這個虛存區(qū)就由mmap_cache指向。共一百六十九頁為什么把進程的用戶空間分
16、成一個個空間,這是因為每個虛存區(qū)的來源可能不同,有的來自可執(zhí)行映像,有的來自共享庫,而有的則可能是動態(tài)分配的內存區(qū)。不同的區(qū)間可能具有不同的訪問權限(qunxin),不同的操作。因此Linux把進程的用戶空間分割,并利用了虛存區(qū)處理函數(shù)(vm_ops)來抽象對不同來源的虛存區(qū)的處理方法。虛存區(qū)共一百六十九頁struct vm_area_struct struct mm_struct * vm_mm; unsigned long vm_start; unsigned long vm_end; pgprot_t vm_page_prot; unsigned short vm_flags; stru
17、ct vm_area_struct *vm_next; short vm_avl_height; struct vm_area_struct *vm_avl_left, *vm_avl_right; struct vm_operations_struct * vm_ops; struct vm_area_struct *vm_next_share, *vm_pprev_share; unsigned long vm_offset; struct file * vm_file; unsigned long vm_pte; ; VM_AREA_STRUCT 結構(jigu) 共一百六十九頁域名說
18、明vm_mm指向虛存區(qū)所在的mm_struct結構的指針。vm_start,vm_end虛存區(qū)的起始地址和終止地址。vm_page_prot虛存區(qū)的保護權限。vm_flags虛存區(qū)的標志。vm_next構成線性鏈表的指針,按虛存區(qū)基址從小到大排列。vm_avl_height,vm_avl_left,vm_avl_right這3個域在一起構成AVL樹,其中vm_avl_height是該節(jié)點距根節(jié)點的高度,vm_avl_left和vm_avl_right分別是該節(jié)點的左右兩個子樹。vm_ops對虛存區(qū)進行操作的函數(shù)。這些給出了可以對虛存區(qū)中的頁所進行的操作。共一百六十九頁根據(jù)虛擬內存抽象模型(mx
19、ng),每個進程都可以互不干擾的使用所有虛擬地址。進程的虛擬內存空間被劃分為小的虛擬內存區(qū)域來使用。每個內存區(qū)域是一段具有相同屬性的虛擬地址空間。Linux用vm_area_struct(include/linux/mm.h)來描述一個虛擬內存區(qū)域。一個進程的所有內存區(qū)域組織成一個雙向鏈表。進程用了一個指向vm_area_struct鏈表的指針,來描述進程虛擬內存空間的一個區(qū)域,包括對該區(qū)域的起始和終止地址的描述。進程可以通過vm_operation_struct(include/linux/mm.h)對這些區(qū)域進行操作。虛存區(qū)共一百六十九頁Linux在這里利用了面向對象的思想,即把一個虛存區(qū)
20、看成一個對象,用vm_area_structs描述了這個對象的屬性,其中的vm_operation結構描述了在這個對象上的操作,其定義如下:struct vm_operations_struct void (*open)(struct vm_area_struct * area); void (*close)(struct vm_area_struct * area);struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int unused) vm_operations結構中包含的是函數(shù)指針;
21、其中,open、close分別用于虛存區(qū)的打開、關閉,而nopage是當虛存頁面不在物理內存而引起的“缺頁異?!睍r所應該(ynggi)調用的函數(shù)。 虛存區(qū)共一百六十九頁當加載關于進程虛擬地址空間的頁面時,一系列的vm_area_struct將自動生成,每一個vm_area_struct描述進程的一部分,如執(zhí)行代碼、數(shù)據(jù)等。Linux支持了多數(shù)標準的虛擬內存操作,如讀取、關閉、共享、缺頁等。一旦(ydn)vm_area_struct結構生成,就可以通過該結構中的指向vm_operation_struct的指針進行虛擬內存操作了虛存區(qū)共一百六十九頁Linux對于虛存區(qū)的操作定義在vm_operat
22、ion_ struct數(shù)據(jù)結構(sh j ji u)中,通過在vm_area_struct結構中使用指針vm_ops來確定該虛存區(qū)可以進行的一系列操作struct vm_operations_struct /* 打開操作,當內核生成一個虛存區(qū)后或者當虛存區(qū)被復制后,就用該命令打開。*/void (*open)(struct vm_area_struct * area);/* 關閉操作,當內核銷毀一個虛存區(qū)時,就調用該命令。*/void (*close)(struct vm_area_struct * area); 虛存區(qū)共一百六十九頁/* 處理缺頁異常,當進程訪問一個不屬于內存的有效頁面時,就
23、會調用該命令(mng lng),返回該頁的物理地址。*/ void (*nopage)(int error_code, struct vm_area_struct * area, unsigned long address);虛存區(qū)共一百六十九頁進程控制塊是內核中的核心數(shù)據(jù)結構。在進程的 task_struct 結構中包含一個mm域,它是指向 mm_struct 結構的指針。而進程的 mm_struct結構則包含進程的可執(zhí)行(zhxng)映像信息以及進程的頁目錄指針pgd等。該結構還包含有指向 vm_area_struct 結構的幾個指針,每個 vm_area_struct 代表進程的一個虛擬
24、地址區(qū)間。 相關數(shù)據(jù)結構(sh j ji u)間的關系共一百六十九頁相關數(shù)據(jù)結構(sh j ji u)之間的關系示意圖 共一百六十九頁系統(tǒng)以用戶虛擬內存地址的降序排列 vm_area_struct。在進程的運行(ynxng)過程中,Linux 要經(jīng)常為進程分配虛存區(qū),因此,vm_area_struct 結構的訪問時間就成了性能的關鍵因素。為此,除鏈表結構外,Linux 還利用AVL平衡樹樹來組織 vm_area_struct。通過這種樹結構,Linux 可以快速定位某個虛存區(qū)。虛存區(qū)共一百六十九頁每個進程都有自己的用戶空間,但是調用clone()函數(shù)創(chuàng)建的內核線程時共享父進程的用戶空間。寫時復
25、制方法,子進程繼承父進程的用戶空間:只要頁是只讀的,就依然共享它們。當其中的一個進程試圖寫入某一個頁時,這個頁就被復制一份;一段時間之后,所創(chuàng)建的進程通常獲得與父進程不一樣的完全屬于自己的用戶空間。而對于(duy)內核線程來說,它使用父進程的用戶空間。因此創(chuàng)建內核線程比創(chuàng)建普通進程相應要快得多,而且只要父進程和子進程謹慎地調整它們的訪問順序,就可以認為頁的共享是有益的。由此,進程用戶空間的創(chuàng)建主要依賴于父進程,而且,在創(chuàng)建的過程中所做的工作僅僅是mm_struc結構的建立,vm_area_struct結構的建立以及頁目錄和頁表的建立,并沒有真正地復制一個物理頁面,這也是為什么Linux內核能迅
26、速地創(chuàng)建進程的原因之一。創(chuàng)建(chungjin)進程用戶空間共一百六十九頁fork()系統(tǒng)調用在創(chuàng)建新進程時也為該進程創(chuàng)建完整的用戶空間具體而言,是通過拷貝或共享父進程的用戶空間來實現(xiàn)的,即內核調用copy_mm( )函數(shù),為新進程建立所有(suyu)頁表和mm_struct結構創(chuàng)建進程(jnchng)用戶空間共一百六十九頁當通過exec()系統(tǒng)調用開始執(zhí)行一個進程時,進程的可執(zhí)行映像(包括代碼段、數(shù)據(jù)段等)必須(bx)裝入到進程的用戶空間。如果該進程用到了任何一個共享庫,則共享庫也必須(bx)裝入到進程的用戶空間由此,Linux并不將映像裝入到物理內存,相反,可執(zhí)行文件只是被連接到進程的用戶
27、空間中。隨著進程的運行,被引用的程序部分會由操作系統(tǒng)裝入到物理內存,這種將映像鏈接到進程用戶空間的方法被稱為“虛存映射” 。虛存映射:即把文件從磁盤映射到進程的用戶空間,對文件的訪問轉化為對虛存區(qū)的訪問虛存映射(yngsh)共一百六十九頁有兩種類型的虛存映射:共享的:有幾個進程共享這一映射,也就是說,如果一個進程對共享的虛存區(qū)進行寫,其它進程都能感覺到,而且會修改磁盤上對應的文件。私有的:進程創(chuàng)建的這種映射只是為了讀文件,而不是寫文件,因此,對虛存區(qū)的寫操作(cozu)不會修改磁盤上的文件,由此可以看出,私有映射的效率要比共享映射的高。除了這兩種映射外,如果映射與文件無關,就叫匿名映射。虛存映
28、射(yngsh)共一百六十九頁當可執(zhí)行映像映射到進程的用戶空間時,將產(chǎn)生一組 vm_area_struct 結構來描述各個虛擬區(qū)間的起始點和終止點每個 vm_area_struct 結構代表可執(zhí)行映像的一部分,可能是可執(zhí)行代碼,可能是初始化的變量或未初始化的數(shù)據(jù),也可能是剛打開的一個文件,這些映射都是在函數(shù)do_mmap()中來實現(xiàn)的隨著 vm_area_struct 結構的生成,這些結構所描述的虛擬內存區(qū)間上的標準操作函數(shù)也由 Linux 初始化。但要明確,在這一步(y b)還沒有建立從虛擬內存到物理內存的映射虛存映射(yngsh)共一百六十九頁例:exam.cint main()print
29、f(“virtual area test!”);進程(jnchng)的虛存區(qū)舉例地址范圍許可權偏移量 所映射的文件08048000-08049000 r-xp00000000/home/test/exam08049000-0804a000rw-p 00001000/home/test/exam 40000000-40015000r-xp00000000/lib/ld-2.3.2.so40015000-40016000rw-p00015000/lib/ld-2.3.2.so40016000-40017000rw-p00000000匿名4002-xp 00000000/
30、lib/libc-2.3.2.so40159000-4015e000rw-p0012f000/lib/libc-2.3.2.so4015w-p00000000匿名bfffe000-c0000000 rwxpfffff000匿名 exam進程(jnchng)的虛存區(qū) 共一百六十九頁地址范圍許可權偏移量 所映射的文件08048000-08049000 r-xp00000000/home/test/exam08049000-0804a000rw-p 00001000/home/test/exam 40000000-40015000r-xp00000000/lib/ld-2
31、.3.2.so40015000-40016000rw-p00015000/lib/ld-2.3.2.so40016000-40017000rw-p00000000匿名4002-xp 00000000/lib/libc-2.3.2.so40159000-4015e000rw-p0012f000/lib/libc-2.3.2.so4015w-p00000000匿名bfffe000-c0000000 rwxpfffff000匿名從0 x8048000開始的虛存區(qū)是/home/test/exam文件的某一部分的虛存映射,范圍從0到0 x1000字
32、節(jié)。許可權指定這個區(qū)域(qy)是可執(zhí)行的(包含目標代碼)、只讀的(不可寫,因為指令執(zhí)行期間不能改變),并且是私有的,因此我們可以猜出這個區(qū)域(qy)映射了程序的代碼段。共一百六十九頁地址范圍許可權偏移量 所映射的文件08048000-08049000 r-xp00000000/home/test/exam08049000-0804a000rw-p 00001000/home/test/exam 40000000-40015000r-xp00000000/lib/ld-2.3.2.so40015000-40016000rw-p00015000/lib/ld-2.3.2.so40016000-40
33、017000rw-p00000000匿名4002-xp 00000000/lib/libc-2.3.2.so40159000-4015e000rw-p0012f000/lib/libc-2.3.2.so4015w-p00000000匿名bfffe000-c0000000 rwxpfffff000匿名從0 x8049000開始(kish)的虛存區(qū)是/home/test/exam文件的另一部分虛存映射,因為許可權指定這個私有區(qū)域可以被寫,我們可以推斷出它映射了程序的數(shù)據(jù)段。共一百六十九頁地址范圍許可權偏移量 所映射的文件08048000-08
34、049000 r-xp00000000/home/test/exam08049000-0804a000rw-p 00001000/home/test/exam 40000000-40015000r-xp00000000/lib/ld-2.3.2.so40015000-40016000rw-p00015000/lib/ld-2.3.2.so40016000-40017000rw-p00000000匿名4002-xp 00000000/lib/libc-2.3.2.so40159000-4015e000rw-p0012f000/lib/libc-2.3.2.so4015
35、w-p00000000匿名bfffe000-c0000000 rwxpfffff000匿名類似地,從0 x40000000、0 x40015000開始的虛存區(qū)分別(fnbi)對應動態(tài)鏈接庫/lib/ld-2.3.2.so的 代碼段和數(shù)據(jù)段。從40016000開始的虛存區(qū)是匿名的,也就是說,它與任何文件都無關,可以推斷出它映射了連接程序的bbs段(未初始化的數(shù)據(jù)段)。共一百六十九頁地址范圍許可權偏移量 所映射的文件08048000-08049000 r-xp00000000/home/test/exam08049000-0804a000rw-p 00001000/ho
36、me/test/exam 40000000-40015000r-xp00000000/lib/ld-2.3.2.so40015000-40016000rw-p00015000/lib/ld-2.3.2.so40016000-40017000rw-p00000000匿名4002-xp 00000000/lib/libc-2.3.2.so40159000-4015e000rw-p0012f000/lib/libc-2.3.2.so4015w-p00000000匿名bfffe000-c0000000 rwxpfffff000匿名緊接著的三個區(qū)映
37、射了C庫程序/lib/libc-2.3.2.so的代碼段、數(shù)據(jù)段和bss段。最后(zuhu)一個虛擬區(qū)是進程的堆棧。 共一百六十九頁與用戶空間相關的主要(zhyo)系統(tǒng)調用 系統(tǒng)調用描述fork()創(chuàng)建具有新的用戶空間的進程,用戶空間中的所有頁被標記為“寫時復制”,且由父子進程共享,當其中的一個進程所訪問的頁不在內存時,這個頁就被復制一份。mmap()在進程的用戶空間內創(chuàng)建一個新的虛存區(qū)。munmap()銷毀一個完整的虛存區(qū)或其中的一部分,如果要取消的虛存區(qū)位于某個虛存區(qū)的中間,則這個虛存區(qū)被劃分為兩個虛存區(qū)。exec()裝入新的可執(zhí)行文件以代替當前用戶空間。exit()銷毀進程的用戶空間及其
38、所有的虛存區(qū)。共一百六十九頁與用戶空間相關的主要(zhyo)系統(tǒng)調用 對fork()、exec()、exit()這幾個系統(tǒng)調用(dioyng)已有所了解,下面說明在用戶程序中如何調用(dioyng)mmap(),其原型為:void *mmap (void *start , int length, int prot, int flags, int fd, int offset) start為映射到用戶空間的起始地址 length則為長度(以字節(jié)為單位) 參數(shù)prot表示對所映射區(qū)間的訪問模式,如可寫、可讀、可執(zhí)行等 參數(shù)fd代表一個已打開的文件 offset為文件的起點共一百六十九頁與用戶空間相
39、關的主要(zhyo)系統(tǒng)調用 對fork()、exec()、exit()這幾個系統(tǒng)調用已有所了解,下面說明在用戶程序中如何調用mmap(),其原型為:void *mmap (void *start , int length, int prot, int flags, int fd, int offset)而flags用于其他控制目的:MAP_SHARED:與子進程共享虛存區(qū),則對映射(yngsh)的內存所做的修改同樣影響到文件。MAP_PRIVATE: 子進程對這個虛存區(qū)是“寫時拷貝”,對映射的內存所做的修改僅對該進程可見,對文件沒有影響。MAP_LOCKED:鎖定這個虛存區(qū),不能交換。MAP
40、_ANONYMOUS:匿名區(qū),與文件無關共一百六十九頁與用戶(yngh)空間相關的主要系統(tǒng)調用 mmap系統(tǒng)調用并不是完全為了(wi le)用于共享內存而設計的。它本身提供了不同于一般對普通文件的訪問方式,進程可以像讀寫內存一樣對普通文件的操作。另外,mmap()實現(xiàn)共享內存也是其主要應用之一。 mmap系統(tǒng)調用使得進程之間通過映射同一個普通文件實現(xiàn)共享內存。普通文件被映射到進程地址空間后,進程可以像訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。通常使用了mmap,為了“像訪問普通內存一樣對文件進行訪問”。實踐證明,當要對一個文件頻繁的進行訪問,并且指針來回移動
41、時,調用mmap比用常規(guī)的方法快很多。共一百六十九頁與用戶空間相關的主要(zhyo)系統(tǒng)調用 共一百六十九頁與用戶空間相關的主要系統(tǒng)(xtng)調用 例子,下面的程序段映射一個4字節(jié)大小(dxio)的匿名區(qū),父進程和子進程共享這個匿名區(qū)。#define N 10int i, sum, fd;int *result_ptr = mmap(0, 4, PROT_READ|PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0 , 0);int pid = fork();if (pid =0)for(sum=0, i=1; i=N; i+) sum+=i;*result_
42、ptr=sum;elsewait(0);printf(“result=%dn”, *result_ptr);共一百六十九頁與用戶空間相關(xinggun)的主要系統(tǒng)調用 例子(l zi),下面的程序段映射一個名為test_data的文件,文件的內容為“Hello,World!”int i, fd;char* buf;fd = open(“test_data”, O_RDONLY);buf = mmap(0, 12, PROT_READ, MAP_PRIVATE, fd, 0);for(i=0; i0:頁已經(jīng)分配給一個或多個進程或用戶某些內核數(shù)據(jù)結構flags:頁框狀態(tài),最多可以有32個,每個使
43、用一個位表示共一百六十九頁頁框狀態(tài)(zhungti)在磁盤(c pn)I/O操作中涉及的頁在傳輸頁時發(fā)生I/O錯誤為一次I/O操作剛剛訪問過的頁在完成讀操作后置位,除非發(fā)生磁盤I/O錯誤頁已經(jīng)被修改頁在活動或非活動的鏈表中頁在活動頁鏈表中包含在slab中的頁框頁框屬于ZONE_HIGHMEM管理區(qū)由ext2文件系統(tǒng)使用的標志在x86體系結構上沒有使用頁框留給內核代碼使用或沒有使用共一百六十九頁隨著用戶程序的執(zhí)行和結束,系統(tǒng)需要不斷為其分配和釋放物理頁面。內核應該為分配一組連續(xù)的頁面而建立一種穩(wěn)定、高效的分配策略。但是,頻繁地請求和釋放不同大小的一組連續(xù)頁面,必然導致在已分配的內存(ni cn)
44、塊中分撒著許多小塊的空閑頁面,即外碎片。由此帶來的問題是,即使這些小塊的空閑頁面加起來足以滿足所請求的頁面,但是要分配一個大塊的連續(xù)頁面可能根本無法滿足。為此,Linux使用著名的伙伴(buddy)算法來解決外碎片問題。物理內存(ni cn)的分配與回收 共一百六十九頁Linux采用著名的伙伴(Buddy)算法(sun f)來解決外碎片問題伙伴算法把所有的空閑頁面分為10個塊鏈表,每個鏈表中的一個塊含有2的冪次個頁面(叫做“頁塊”或簡稱“塊” )例如,第0個鏈表中塊的大小都是20(1個頁面),第1個鏈表中塊的大小都為21(1個頁面),第9個鏈表中塊的大小都為29(512個頁面)伙伴算法采用的是
45、free_area的數(shù)組,定義如下:Struct free_area_structStruct page *next;Struct page *prev;Unsigned int *map; free_area10;頁面(y min)分配與回收算法伙伴算法共一百六十九頁滿足以下條件的兩個塊稱為伙伴:兩個塊的大小相同兩個塊的物理地址連續(xù)伙伴算法把滿足以上條件的兩個塊合并為一個塊工作原理:首先在大小滿足要求的塊鏈表中查找是否(sh fu)有空閑塊,若有則直接分配,否則在更大的塊中查找。其逆過程就是塊的釋放,此時會把滿足伙伴關系的塊合并頁面分配與回收(hushu)算法伙伴算法共一百六十九頁例如,假設
46、(jish)要請求一個128個頁框的塊,算法先檢查128個頁框的鏈表是否有空閑塊,如果沒有則查256個頁框的鏈表,有則將256個頁框的塊分裂兩份,一份使用,一份插入128個頁框的鏈表。如果還沒有,就查512個頁框的鏈表,有的話就分裂為128,128,256,一個128使用,剩余兩個插入對應鏈表。如果在512還沒查到,則返回出錯信號回收過程相反,內核試圖把大小為b的空閑伙伴合并為一個大小為2b的單獨快,如果成功合并所釋放的塊,會試圖合并2b的塊來形成更大 的塊。 頁面分配(fnpi)與回收算法伙伴算法共一百六十九頁Linux使用伙伴算法(sun f)有效地分配和回收物理頁塊。該算法(sun f)
47、試圖分配由一個或多個連續(xù)物理頁面組成的內存塊,其大小為1頁,2頁,或4頁等。只要系統(tǒng)有滿足需要的足夠的空閑頁面,就會在free_area數(shù)組中查找滿足需要大小的一個頁塊函數(shù)_get_free_pages 用于分配物理頁塊該函數(shù)所做的工作如下:檢查所請求的頁塊大小是否能夠被滿足檢查系統(tǒng)中空閑物理頁的總數(shù)是否已低于允許的下界正常分配。從free_area數(shù)組的第order項開始,這是一個mem_map_t鏈表換頁。通過下列語句調用函數(shù)try_to_free_ pages(),啟動換頁進程物理(wl)頁面的分配共一百六十九頁1.如果該鏈表中有滿足要求的頁塊,則:將其從鏈表中摘下;將free_area
48、數(shù)組的位圖中該頁塊所對應的位取反,表示頁塊已用;修改全局變量nr_free_pages(減去分配出去的頁數(shù));根據(jù)該頁塊在mem_map數(shù)組中的位置,算出其起始(q sh)物理地址,返回。共一百六十九頁2.如果該鏈表中沒有滿足要求的頁塊,則在free_area數(shù)組中順序向上查找。其結果有二:a. 整個free_area數(shù)組中都沒有滿足要求的頁塊,此次無法分配,返回。b. 找到一個滿足要求的頁塊,則將其從鏈表中摘下;將free_area數(shù)組的位圖中該頁塊所對應的位取反,表示頁塊已用;修改全局變量nr_free_pages(減去分配出去的頁數(shù));因為頁塊比申請的頁塊要大,所以要將它分成適當大小(d
49、xio)的塊。因為所有的頁塊都由2的冪次的頁數(shù)組成,所以這個分割的過程比較簡單,只需要將它平分就可以:I. 將其平分為兩個伙伴,將小伙伴加入free_area數(shù)組中相應的鏈表,修改位圖中相應的位;II.如果大伙伴仍比申請的頁塊大,則轉I,繼續(xù)劃分;III.大伙伴的大小正是所要的大小,修改位圖中相應的位,根據(jù)其在mem_map數(shù)組中的位置,算出它的起始物理地址,返回。 共一百六十九頁分配頁塊的過程將大的頁塊劃分為小的頁塊,會使內存更為零散。頁回收(hushu)的過程與頁分配的過程相反,它會盡可能把小頁塊合并為大頁塊函數(shù)free_pages用于頁塊的回收void free_pages(unsign
50、ed long addr, unsigned long order) addr是要回收的頁塊的首地址,order表示要收回頁塊的大小為2的order次冪個物理頁物理頁面(y min)的回收共一百六十九頁函數(shù)free_pages所做的工作如下:根據(jù)頁塊的首地址addr算出該塊的第一頁在mem_map數(shù)組的索引(suyn);如果該頁是保留的(內核在使用),則不允許回收;將頁塊第一頁對應的mem_map_t結構中的count域減1,表示引用該頁的進程數(shù)減了1個。若count域的值不為0,有別的進程在使用該頁塊,不能回收,僅簡單返回;清除頁塊第一頁對應的mem_map_t結構中flags域的PG_re
51、ferenced位,表示該頁塊不再被引用;將全局變量nr_free_pages的值加上回收的物理頁數(shù)將頁塊加入到數(shù)組free_area的相應鏈表中 物理頁面(y min)的回收共一百六十九頁將頁塊加入到數(shù)組free_area的相應聯(lián)表中時,要加入的鏈表由order參數(shù)指定,即將頁塊加入到free_areaorder鏈表中。加入的過程如下:1)檢查free_areaorder的位圖map,看該頁塊的伙伴是否(sh fu)已在鏈表中。對大小為2的order冪次的頁塊,假定其開始頁在mem_map數(shù)組中的索引為map_nr,則計算其伙伴在mem_map數(shù)組中的索引檢查的結果有二:a. 其伙伴不在鏈表
52、中,說明該頁塊的伙伴還在使用,不需要合并。此時只需將位圖中該頁塊相應的位取反,表示頁塊已經(jīng)自由;將其加入到free_areaorder鏈表的頭部。b. 其伙伴在鏈表中,說明頁塊及其伙伴均獲得自由,可以將它們合并成更大的頁塊。將頁塊的伙伴從鏈表中摘下,將它們在位圖中對應的位取反,表示頁塊已不可用;計算新的大頁塊在mem_map數(shù)組中的索引(頁塊索引和伙伴索引的小者);order+,回到算法開始,將大頁塊加入到數(shù)組free_area的相應鏈表中。 物理(wl)頁面的回收共一百六十九頁Slab分配模式在操作系統(tǒng)的運作過程中,經(jīng)常會涉及到大量對象的重復生成、使用和釋放問題。對象生成算法的改進,可以在很
53、大程度上提高整個系統(tǒng)的性能。在Linux系統(tǒng)中所用到的對象,比較典型的例子是inode、task_struct等, 都又這些特點。一般,這類對象的種類相對穩(wěn)定,每種對象的數(shù)量卻是巨大的,并且在初始化與析構時要做大量的工作,所占用的時間遠遠超過(chogu)內存分配的時 間。但是這些對象往往具有這樣一個性質,即他們在生成時,所包括的成員屬性值一般都賦成確定的數(shù)值,并且在使用完畢,釋放結構前,屬性又恢復為未使用 前的狀態(tài)。因此,如果我們能夠用合適的方法使得在對象前后兩次被使用時,在同一塊內存,或同一類內存空間,且保留了基本的數(shù)據(jù)結構,就可以大大提高效率。slab算法就是針對上述特點設計的。共一百六
54、十九頁Slab分配模式單單分配頁面的分配器肯定是不能滿足要求的 內核中大量使用各種數(shù)據(jù)結構,大小從幾個字節(jié)到幾十上百k不等,都取整到2的冪次個頁面那是完全不現(xiàn)實的 早期內核的解決方法是提供大小為2, 4, 8, 16, ., 131056字節(jié)的內存區(qū)域 需要新的內存區(qū)域時,內核從伙伴(hubn)系統(tǒng)申請頁面,把它們劃分成一個個區(qū)域,取一個來滿足需求 如果某個頁面中的內存區(qū)域都釋放了,頁面就交回到伙伴系統(tǒng) 共一百六十九頁但這種分配方法有許多值得改進的地方:不同的數(shù)據(jù)類型用不同的方法分配內存可能提高效率。比如需要初始化的數(shù)據(jù)結構,釋放后可以暫存著,再分配時就不必初始化了 內核的函數(shù)常常重復地使用同
55、一類型的內存區(qū),緩存最近釋放的對象可以加速分配和釋放 對內存的請求可以按照請求頻率來分類,頻繁使用的類型使用專門的緩存,很少使用的可以使用通用緩存使用2的冪次大小的內存區(qū)域時硬件高速緩存沖突的概率較大,有可能通過仔細安排內存區(qū)域的起始地址來減少(jinsho)硬件高速緩存沖突 緩存一定數(shù)量的對象可以減少對buddy系統(tǒng)的調用,從而節(jié)省時間并減少由此引起的硬件高速緩存污染 共一百六十九頁Slab機制提出的原因:為了減少對伙伴算法的調用次數(shù) 內核經(jīng)常反復使用某一內存區(qū) 內存區(qū)可根據(jù)其使用頻率(pnl)來分類 硬件高速緩存的使用,為盡量減少對伙伴算法的調用提供了另一個理由Slab 分配(fnpi)機
56、制分配(fnpi)小內存共一百六十九頁slab分配器slab分配器體現(xiàn)了這些改進思想slab分配器把內存區(qū)看成對象slab分配器把對象分組放進高速緩存。每個高速緩存都是同種類型內存對象的一種“儲備”例如當一個文件被打開時,存放相應“打開文件”對象所需的內存是從一個叫做filp(file pointer)的slab分配器的高速緩存中得到(d do)的也就是說每種對象類型對應一個高速緩存共一百六十九頁Slab分配模式把對象分組放進緩沖區(qū) Slab緩沖區(qū)由一連串的“大塊(d kui)(Slab)”構成,每個大塊中包含若干個同種類型的對象,這些對象或已被分配,或空閑 簡言之,緩沖區(qū)就是主存中的一片區(qū)域
57、,把這片區(qū)域劃分為多個塊,每塊就是一個Slab,每個Slab由一個或多個頁面組成,每個Slab中存放的就是對象 Slab 分配(fnpi)機制分配(fnpi)小內存共一百六十九頁每個高速緩存被分成多個(du )slabs,每個slab由一個或多個(du )連續(xù)的頁框組成,其中包含一定數(shù)目的對象共一百六十九頁每個slab有三種狀態(tài):全滿,半滿,全空全滿意味著slab中的對象全部已被分配出去全空意味著slab中的對象全部是可用的半滿介于兩者之間當內核函數(shù)需要一個新的對象時,優(yōu)先從半滿的slab滿足這個請求否則從全空的slab中取一個對象滿足請求如果(rgu)沒有空的slab則向buddy系統(tǒng)申請頁
58、面生成一個新的slab共一百六十九頁專用緩沖區(qū)主要用于頻繁使用的數(shù)據(jù)結構,如task_struct、mm_struct、vm_area_struct、file、dentry、inode等緩沖區(qū)是用kmem_cache_t類型描述的,通過kmem_cache_create()來建立 函數(shù)kmem_cache_create()所創(chuàng)建的緩沖區(qū)中還沒有包含(bohn)任何Slab,因此,也沒有空閑的對象。只有以下兩個條件都為真時,才給緩沖區(qū)分配Slab:已發(fā)出一個分配新對象的請求;緩沖區(qū)不包含任何空閑對象; Slab專用緩沖區(qū)的建立(jinl)和釋放 共一百六十九頁在內核中初始化開銷不大的數(shù)據(jù)結構(s
59、h j ji u)可以合用一個通用的緩沖區(qū)通用緩沖區(qū)類似于物理頁面分配中的大小分區(qū),最小的為32字節(jié),然后依次為64、128,直至128KB(即32個頁面)對通用緩沖區(qū)的管理采用Slab方式當一個數(shù)據(jù)結構的使用不頻繁、或其大小不足一個頁面時,沒有必要給其分配專用緩沖區(qū) ,可調用函數(shù)kmallo() 分配通用緩沖區(qū)。如果數(shù)據(jù)結構的大小接近一個頁面,則可通過調用_get_free_page()為止分配一個頁面通用(tngyng)緩沖區(qū)共一百六十九頁從通用緩沖區(qū)中分配和釋放緩沖區(qū)的函數(shù)為:void *kmalloc(size_t size, int flags);Void kree(const vo
60、id *objp); 事實上,在內核中,尤其是驅動程序中,有大量的數(shù)據(jù)結構僅僅是一次性使用,而且所占內存只有幾十個字節(jié),因此,一般調用kmalloc()給內核數(shù)據(jù)結構分配內存就足夠另外,因為在Linux2.0以前的版本一般都調用kmallo()給內核數(shù)據(jù)結構分配內存,因此,調用該函數(shù)的一個優(yōu)點是讓你開發(fā)的驅動程序能保持向后兼容kfree()函數(shù)釋放由kmalloc()分配出來的內存塊。如果想要釋放的內存不是由kmalloc()分配的,或者想要釋放的內存早就被釋放過了,比如說釋放屬于內核其它部分的內存,調用這個函數(shù)會導致嚴重(ynzhng)的后果通用(tngyng)緩沖區(qū)共一百六十九頁任何(rn
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 住宅小區(qū)外墻改造協(xié)議
- 礦泉水廠保溫系統(tǒng)安裝協(xié)議
- 網(wǎng)絡短視頻副導演招聘協(xié)議
- 裝飾裝修勞務協(xié)議
- 市場調研門頭租賃合同
- 污水處理工程勞務合同模板
- 創(chuàng)業(yè)學校租賃合同
- 花藝作品銷售顧問聘用協(xié)議
- 建筑工程施工合同:生態(tài)保護工程
- 花園租賃協(xié)議模板
- 龍口粉絲行業(yè)分析
- 《跨境電商應用英語1》課程標準
- 醫(yī)保集采工作總結
- 匾額制作工藝
- 維護社會穩(wěn)定規(guī)定
- 急性心力衰竭通用課件
- 醫(yī)療廢物的減量化處理方法與技術
- 中國心血管病風險評估和指南
- 建筑結構抗震能力評估技術
- 金融業(yè)就業(yè)課件
- 四年級《梯形的認識》
評論
0/150
提交評論