




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、.Linux內存管理 以程序員視角Linux內存管理摘要:本章首先以應用程序開發者的角度審視Linux的進程內存管理,在此根底上逐步深化到內核中討論系統物理內存管理和內核內存的使用方法。力求從外到內、水到渠成地引導網友分析Linux的內存管理與使用。在本章最后,我們給出一個內存映射的實例,幫助網友們理解內核內存管理與用戶內存管理之間的關系,希望大家最終能駕馭Linux內存管理。前言內存管理一向是所有操作系統書籍不惜筆墨重點討論的內容,無論市面上或是網上都充滿著大量涉及內存管理的教材和資料。因此,我們這里所要寫的Linux內存管理采取避重就輕的策略,從理論層面就不去班門弄斧,貽笑大方了。我們最想
2、做的和可能做到的是從開發者的角度談談對內存管理的理解,最終目的是把我們在內核開發中使用內存的經歷和對Linux內存管理的認識與大家共享。當然,這其中我們也會涉及到一些諸如段頁等內存管理的根本理論,但我們的目的不是為了強調理論,而是為了指導理解開發中的理論,所以僅僅點到為止,不做深究。遵循"理論來源于理論"的"教條",我們先不必一下子就鉆入內核里去看系統內存到底是如何管理,那樣往往會讓你陷入似懂非懂的窘境我當年就犯了這個錯誤!。所以最好的方式是先從外部用戶編程范疇來觀察進程如何使用內存,等到大家對內存的使用有了較直觀的認識后,再深化到內核中去學習內存如何被
3、管理等理論知識。最后再通過一個實例編程將所講內容融會貫穿。進程與內存進程如何使用內存?毫無疑問,所有進程執行的程序都必須占用一定數量的內存,它或是用來存放從磁盤載入的程序代碼,或是存放取自用戶輸入的數據等等。不過進程對這些內存的管理方式因內存用處不一而不盡一樣,有些內存是事先靜態分配和統一回收的,而有些卻是按需要動態分配和回收的。對任何一個普通進程來講,它都會涉及到5種不同的數據段。稍有編程知識的朋友都能想到這幾個數據段中包含有"程序代碼段"、"程序數據段"、"程序堆棧段"等。不錯,這幾種數據段都在其中,但除了以上幾種數據段之外,進程
4、還另外包含兩種數據段。下面我們來簡單歸納一下進程對應的內存空間中所包含的5種不同的數據區。代碼段:代碼段是用來存放可執行文件的操作指令,也就是說是它是可執行程序在內存中的鏡像。代碼段需要防止在運行時被非法修改,所以只準許讀取操作,而不允許寫入修改操作-它是不可寫的。數據段:數據段用來存放可執行文件中已初始化全局變量,換句話說就是存放程序靜態分配的變量和全局變量。BSSBSS段包含了程序中未初始化的全局變量,在內存中bss段全部置零。堆heap:堆是用于存放進程運行中被動態分配的內存段,它的大小并不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上堆被
5、擴張;當利用free等函數釋放內存時,被釋放的內存從堆中被剔除堆被縮減棧:棧是用戶存放程序臨時創立的部分變量,也就是說我們函數括弧""中定義的變量但不包括static聲明的變量,static意味著在數據段中存放變量。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,并且待到調用完畢后,函數的返回值也會被存放回棧中。由于棧的先進先出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個存放、交換臨時數據的內存區。進程如何組織這些區域?上述幾種內存區域中數據段、BSS和堆通常是被連續存儲的-內存位置上是連續的,而代碼段和棧往往會被獨立存放
6、。有趣的是,堆和棧兩個區域關系很"曖昧",他們一個向下"長"i386體系構造中棧向下、堆向上,一個向上"長",相對而生。但你不必擔憂他們會碰頭,因為他們之間間隔很大到底大到多少,你可以從下面的例子程序計算一下,絕少有時機能碰到一起。以下圖簡要描繪了進程內存區域的分布:"事實勝于雄辯",我們用一個小例子原形取自?User-Level Memory Management?來展示上面所講的各種內存區的差異與位置。includestdio.h includemalloc.h includeunistd.h int bss_
7、var;int data_var0=1;int mainint argc,char*argvprintf"below are addresses of types of process's memn";printf"Text location:n";printf"tAddress of mainCode Segment:%pn",main;printf"_n";int stack_var0=2;printf"Stack Location:n";printf"tInitial e
8、nd of stack:%pn",&stack_var0;int stack_var1=3;printf"tnew end of stack:%pn",&stack_var1;printf"_n";printf"Data Location:n";printf"tAddress of data_varData Segment:%pn",&data_var0;static int data_var1=4;printf"tNew end of data_varData Segm
9、ent:%pn",&data_var1;printf"_n";printf"BSS Location:n";printf"tAddress of bss_var:%pn",&bss_var;printf"_n";char*b=sbrkptrdiff_t0;printf"Heap Location:n";printf"tInitial end of heap:%pn",b;brkb+4;b=sbrkptrdiff_t0;printf"tNew
10、 end of heap:%pn",b;return 0;它的結果如下below are addresses of types of process's mem Text location:Address of mainCode Segment:0x 8048388 _Stack Location:Initial end of stack:0xbffffab4 new end of stack:0xbffffab0 _Data Location:Address of data_varData Segment:0x 8049758 New end of data_varData
11、 Segment:0x 804975c _BSS Location:Address of bss_var:0x 8049864 _Heap Location:Initial end of heap:0x 8049868 New end of heap:0x 804986c利用size命令也可以看到程序的各段大小,比方執行size example會得到text data bss dec hex filename 1654 2808 1942 796 example但這些數據是程序編譯的靜態統計,而上面顯示的是進程運行時的動態值,但兩者是對應的。通過前面的例子,我們對進程使用的邏輯內存分布已先睹為
12、快。這部分我們就繼續進入操作系統內核看看,進程對內存詳細是如何進展分配和管理的。從用戶向內核看,所使用的內存表象形式會依次經歷"邏輯地址"-"線性地址"-"物理地址"幾種形式關于幾種地址的解釋在前面已經講述了。邏輯地址經段機制轉化成線性地址;線性地址又經過頁機制轉化為物理地址。但是我們要知道Linux系統雖然保存了段機制,但是將所有程序的段地址都定死為0-4G,所以雖然邏輯地址和線性地址是兩種不同的地址空間,但在Linux中邏輯地址就等于線性地址,它們的值是一樣的。沿著這條線索,我們所研究的主要問題也就集中在下面幾個問題。1.進程空間
13、地址如何管理?2.進程地址如何映射到物理內存?3.物理內存如何被管理?以及由上述問題引發的一些子問題。如系統虛擬地址分布;內存分配接口;連續內存分配與非連續內存分配等。進程內存空間Linux操作系統采用虛擬內存管理技術,使得每個進程都有各自互不干預的進程地址空間。該空間是塊大小為4G的線性虛擬空間,用戶所看到和接觸到的都是該虛擬地址,無法看到實際的物理內存地址。利用這種虛擬地址不但能起到保護操作系統的效果用戶不能直接訪問物理內存,而且更重要的是,用戶程序可使用比實際物理內存更大的地址空間詳細的原因請看硬件根底部分。在討論進程空間細節前,這里先要澄清下面幾個問題:l第一、4G的進程地址空間被人為
14、的分為兩個部分-用戶空間與內核空間。用戶空間從0到3G0xC 0000000,內核空間占據3G到4G。用戶進程通常情況下只能訪問用戶空間的虛擬地址,不能訪問內核空間虛擬地址。只有用戶進程進展系統調用代表用戶進程在內核態執行等時刻可以訪問到內核空間。l第二、用戶空間對應進程,所以每當進程切換,用戶空間就會跟著變化;而內核空間是由內核負責映射,它并不會跟著進程改變,是固定的。內核空間地址有自己對應的頁表init_mm.pgd,用戶進程各自有不同的頁表。l第三、每個進程的用戶空間都是完全獨立、互不相干的。不信的話,你可以把上面的程序同時運行10次當然為了同時運行,讓它們在返回前一同睡眠100秒吧,你
15、會看到10個進程占用的線性地址一模一樣。進程內存管理進程內存管理的對象是進程線性地址空間上的內存鏡像,這些內存鏡像其實就是進程使用的虛擬內存區域memory region。進程虛擬空間是個32或64位的"平坦"獨立的連續區間地址空間空間的詳細大小取決于體系構造。要統一管理這么大的平坦空間可絕非易事,為了方便管理,虛擬空間被劃分為許多大小可變的但必須是4096的倍數內存區域,這些區域在進程線性地址中像停車位一樣有序排列。這些區域的劃分原那么是"將訪問屬性一致的地址空間存放在一起",所謂訪問屬性在這里無非指的是"可讀、可寫、可執行等"。假
16、如你要查看某個進程占用的內存區域,可以使用命令cat/proc/pid/maps獲得pid是進程號,你可以運行上面我們給出的例子-./example&;pid便會打印到屏幕,你可以發現很多類似于下面的數字信息。由于程序example使用了動態庫,所以除了example本身使用的的內存區域外,還會包含那些動態庫使用的內存區域區域順序是:代碼段、數據段、bss段。我們下面只抽出和example有關的信息,除了前兩行代表的代碼段和數據段外,最后一行是進程使用的棧空間。-08048000-08049000 r-xp 0000000003:03 439029/home/mm/src/exampl
17、e 08049000-0804a000 rw-p 0000000003:03 439029/home/mm/src/examplebfffe000-c 0000000 rwxp ffff00000:00 0-每行數據格式如下:內存區域開場-完畢訪問權限偏移主設備號:次設備號i節點文件。注意,你一定會發現進程空間只包含三個內存區域,似乎沒有上面所提到的堆、bss等,其實并非如此,程序內存段和進程地址空間中的內存區域是種模糊對應,也就是說,堆、bss、數據段初始化過的都在進程空間中由數據段內存區域表示。在Linux內核中對應進程內存區域的數據構造是vm_area_struct,內核將每個內存區域作
18、為一個單獨的內存對象管理,相應的操作也都一致。采用面向對象方法使VMA構造體可以代表多種類型的內存區域-比方內存映射文件或進程的用戶空間棧等,對這些區域的操作也都不盡一樣。vm_area_strcut構造比較復雜,關于它的詳細構造請參閱相關資料。我們這里只對它的組織方法做一點補充說明。vm_area_struct是描繪進程地址空間的根本管理單元,對于一個進程來說往往需要多個內存區域來描繪它的虛擬空間,如何關聯這些不同的內存區域呢?大家可能都會想到使用鏈表,確實vm_area_struct構造確實是以鏈表形式鏈接,不過為了方便查找,內核又以紅黑樹以前的內核使用平衡樹的形式組織內存區域,以便降低搜
19、索耗時。并存的兩種組織形式,并非冗余:鏈表用于需要遍歷全部節點的時候用,而紅黑樹適用于在地址空間中定位特定內存區域的時候。內核為了內存區域上的各種不同操作都能獲得高性能,所以同時使用了這兩種數據構造。以下圖反映了進程地址空間的管理模型:進程的地址空間對應的描繪構造是"內存描繪符構造",它表示進程的全部地址空間,-包含了和進程地址空間有關的全部信息,其中當然包含進程的內存區域。進程內存的分配與回收創立進程fork、程序載入execve、映射文件mmap、動態內存分配malloc/brk等進程相關操作都需要分配內存給進程。不過這時進程申請和獲得的還不是實際內存,而是虛擬內存,準
20、確的說是"內存區域"。進程對內存區域的分配最終都會歸結到do_mmap函數上來brk調用被單獨以系統調用實現,不用do_mmap,內核使用do_mmap函數創立一個新的線性地址區間。但是說該函數創立了一個新VMA并不非常準確,因為假如創立的地址區間和一個已經存在的地址區間相鄰,并且它們具有一樣的訪問權限的話,那么兩個區間將合并為一個。假如不能合并,那么就確實需要創立一個新的VMA了。但無論哪種情況,do_mmap函數都會將一個地址區間參加到進程的地址空間中-無論是擴展已存在的內存區域還是創立一個新的區域。同樣,釋放一個內存區域應使用函數do_ummap,它會銷毀對應的內存區
21、域。如何由虛變實!從上面已經看到進程所能直接操作的地址都為虛擬地址。當進程需要內存時,從內核獲得的僅僅是虛擬的內存區域,而不是實際的物理地址,進程并沒有獲得物理內存物理頁面-頁的概念請大家參考硬件根底一章,獲得的僅僅是對一個新的線性地址區間的使用權。實際的物理內存只有當進程真的去訪問新獲取的虛擬地址時,才會由"懇求頁機制"產生"缺頁"異常,從而進入分配實際頁面的例程。該異常是虛擬內存機制賴以存在的根本保證-它會告訴內核去真正為進程分配物理頁,并建立對應的頁表,這之后虛擬地址才實實在在地映射到了系統的物理內存上。當然,假如頁被換出到磁盤,也會產生缺頁異常,
22、不過這時不用再建立頁表了這種懇求頁機制把頁面的分配推延到不能再推延為止,并不急于把所有的事情都一次做完這種思想有點像設計形式中的代理形式proxy。之所以能這么做是利用了內存訪問的"部分性原理",懇求頁帶來的好處是節約了空閑內存,進步了系統的吞吐率。要想更清楚地理解懇求頁機制,可以看看?深化理解linux內核?一書。這里我們需要說明在內存區域構造上的nopage操作。當訪問的進程虛擬內存并未真正分配頁面時,該操作便被調用來分配實際的物理頁,并為該頁建立頁表項。在最后的例子中我們會演示如何使用該方法。系統物理內存管理雖然應用程序操作的對象是映射到物理內存之上的虛擬內存,但是處
23、理器直接操作的卻是物理內存。所以當應用程序訪問一個虛擬地址時,首先必須將虛擬地址轉化成物理地址,然后處理器才能解析地址訪問懇求。地址的轉換工作需要通過查詢頁表才能完成,概括地講,地址轉換需要將虛擬地址分段,使每段虛地址都作為一個索引指向頁表,而頁表項那么指向下一級別的頁表或者指向最終的物理頁面。每個進程都有自己的頁表。進程描繪符的pgd域指向的就是進程的頁全局目錄。下面我們借用?linux設備驅動程序?中的一幅圖大致看看進程地址空間到物理頁之間的轉換關系。上面的過程說起來簡單,做起來難呀。因為在虛擬地址映射到頁之前必須先分配物理頁-也就是說必須先從內核中獲取空閑頁,并建立頁表。下面我們介紹一下
24、內核管理物理內存的機制。物理內存管理頁管理Linux內核管理物理內存是通過分頁機制實現的,它將整個內存劃分成無數個4k在i386體系構造中大小的頁,從而分配和回收內存的根本單位便是內存頁了。利用分頁管理有助于靈敏分配內存地址,因為分配時不必要求必須有大塊的連續內存,系統可以東一頁、西一頁的湊出所需要的內存供進程使用。雖然如此,但是實際上系統使用內存時還是傾向于分配連續的內存塊,因為分配連續內存時,頁表不需要更改,因此能降低TLB的刷新率頻繁刷新會在很大程度上降低訪問速度。鑒于上述需求,內核分配物理頁面時為了盡量減少不連續情況,采用了"伙伴"關系來管理空閑頁面。伙伴關系分配算
25、法大家應該不陌生-幾乎所有操作系統方面的書都會提到,我們不去詳細說它了,假如不明白可以參看有關資料。這里只需要大家明白Linux中空閑頁面的組織和管理利用了伙伴關系,因此空閑頁面分配時也需要遵循伙伴關系,最小單位只能是2的冪倍頁面大小。內核中分配空閑頁面的根本函數是get_free_page/get_free_pages,它們或是分配單頁或是分配指定的頁面2、4、8512頁。get_free_page是在內核中分配內存,不同于malloc在用戶空間中分配,malloc利用堆動態分配,實際上是調用brk系統調用,該調用的作用是擴大或縮小進程堆空間它會修改進程的brk域。假如現有的內存區域不夠包容
26、堆空間,那么會以頁面大小的倍數為單位,擴張或收縮對應的內存區域,但brk值并非以頁面大小為倍數修改,而是按實際懇求修改。因此Malloc在用戶空間分配內存可以以字節為單位分配,但內核在內部仍然會是以頁為單位分配的。另外,需要提及的是,物理頁在系統中由頁構造structpage描繪,系統中所有的頁面都存儲在數組mem_map中,可以通過該數組找到系統中的每一頁空閑或非空閑。而其中的空閑頁面那么可由上述提到的以伙伴關系組織的空閑頁鏈表free_areaMAX_ORDER來索引。內核內存使用Slab所謂尺有所長,寸有所短。以頁為最小單位分配內存對于內核管理系統中的物理內存來說確實比較方便,但內核自身
27、最常使用的內存卻往往是很小遠遠小于一頁的內存塊-比方存放文件描繪符、進程描繪符、虛擬內存區域描繪符等行為所需的內存都缺乏一頁。這些用來存放描繪符的內存相比頁面而言,就好比是面包屑與面包。一個整頁中可以聚集多個這些小塊內存;而且這些小塊內存塊也和面包屑一樣頻繁地生成/銷毀。為了滿足內核對這種小內存塊的需要,Linux系統采用了一種被稱為slab分配器的技術。Slab分配器的實現相當復雜,但原理不難,其核心思想就是"存儲池"的運用。內存片段小塊內存被看作對象,當被使用完后,并不直接釋放而是被緩存到"存儲池"里,留做下次使用,這無疑防止了頻繁創立與銷毀對象所帶
28、來的額外負載。Slab技術不但防止了內存內部分片下文將解釋帶來的不便引入Slab分配器的主要目的是為了減少對伙伴系統分配算法的調用次數-頻繁分配和回收必然會導致內存碎片-難以找到大塊連續的可用內存,而且可以很好地利用硬件緩存進步訪問速度。Slab并非是脫離伙伴關系而獨立存在的一種內存分配方式,slab仍然是建立在頁面根底之上,換句話說,Slab將頁面來自于伙伴關系管理的空閑頁面鏈表撕碎成眾多小內存塊以供分配,slab中的對象分配和銷毀使用kmem_cache_alloc與kmem_cache_free。Kmalloc Slab分配器不僅僅只用來存放內核專用的構造體,它還被用來處理內核對小塊內存
29、的懇求。當然鑒于Slab分配器的特點,一般來說內核程序中對小于一頁的小塊內存的懇求才通過Slab分配器提供的接口Kmalloc來完成雖然它可分配32到131072字節的內存。從內核內存分配的角度來講,kmalloc可被看成是get_free_pages的一個有效補充,內存分配粒度更靈敏了。有興趣的話,可以到/proc/slabinfo中找到內核執行現場使用的各種slab信息統計,其中你會看到系統中所有slab的使用信息。從信息中可以看到系統中除了專用構造體使用的slab外,還存在大量為Kmalloc而準備的Slab其中有些為dma準備的。內核非連續內存分配Vmalloc伙伴關系也好、slab技
30、術也好,從內存管理理論角度而言目的根本是一致的,它們都是為了防止"分片",不過分片又分為外部分片和內部分片之說,所謂內部分片是說系統為了滿足一小段內存區連續的需要,不得不分配了一大區域連續內存給它,從而造成了空間浪費;外部分片是指系統雖有足夠的內存,但卻是分散的碎片,無法滿足對大塊"連續內存"的需求。無論何種分片都是系統有效利用內存的障礙。slab分配器使得一個頁面內包含的眾多小塊內存可獨立被分配使用,防止了內部分片,節約了空閑內存。伙伴關系把內存塊按大小分組管理,一定程度上減輕了外部分片的危害,因為頁框分配不在盲目,而是按照大小依次有序進展,不過伙伴關
31、系只是減輕了外部分片,但并未徹底消除。你自己比劃一下屢次分配頁面后,空閑內存的剩余情況吧。所以防止外部分片的最終思路還是落到了如何利用不連續的內存塊組合成"看起來很大的內存塊"-這里的情況很類似于用戶空間分配虛擬內存,內存邏輯上連續,其實映射到并不一定連續的物理內存上。Linux內核借用了這個技術,允許內核程序在內核地址空間中分配虛擬地址,同樣也利用頁表內核頁表將虛擬地址映射到分散的內存頁上。以此完美地解決了內核內存使用中的外部分片問題。內核提供vmalloc函數分配內核虛擬內存,該函數不同于kmalloc,它可以分配較Kmalloc大得多的內存空間可遠大于128K,但必須
32、是頁大小的倍數,但相比Kmalloc來說,Vmalloc需要對內核虛擬地址進展重映射,必須更新內核頁表,因此分配效率上要低一些用空間換時間與用戶進程相似,內核也有一個名為init_mm的mm_strcut構造來描繪內核地址空間,其中頁表項pdg=swapper_pg_dir包含了系統內核空間3G-4G的映射關系。因此vmalloc分配內核虛擬地址必須更新內核頁表,而kmalloc或get_free_page由于分配的連續內存,所以不需要更新內核頁表。malloc分配的內核虛擬內存與kmalloc/get_free_page分配的內核虛擬內存位于不同的區間,不會重疊。因為內核虛擬空間被分區管理,
33、各司其職。進程空間地址分布從0到3G其實是到PAGE_OFFSET,在0x86中它等于0xC 0000000,從3G到vmalloc_start這段地址是物理內存映射區域該區域中包含了內核鏡像、物理頁面表mem_map等等比方我使用的系統內存是64M可以用free看到,那么3G-3G+64M這片內存就應該映射到物理內存,而vmalloc_start位置應在3G+64M附近說"附近"因為是在物理內存映射區與vmalloc_start期間還會存在一個8M大小的gap來防止躍界,vmalloc_end的位置接近4G說"接近"是因為最后位置系統會保存一片128k
34、大小的區域用于專用頁面映射,還有可能會有高端內存映射區,這些都是細節,這里我們不做糾纏。上圖是內存分布的模糊輪廓由get_free_page或Kmalloc函數所分配的連續內存都陷于物理映射區域,所以它們返回的內核虛擬地址和實際物理地址僅僅是相差一個偏移量PAGE_OFFSET,你可以很方便的將其轉化為物理內存地址,同時內核也提供了virt_to_phys函數將內核虛擬空間中的物理映射區地址轉化為物理地址。要知道,物理內存映射區中的地址與內核頁表是有序對應的,系統中的每個物理頁面都可以找到它對應的內核虛擬地址在物理內存映射區中的。而vmalloc分配的地址那么限于vmalloc_start與v
35、malloc_end之間。每一塊vmalloc分配的內核虛擬內存都對應一個vm_struct構造體可別和vm_area_struct搞混,那可是進程虛擬內存區域的構造,不同的內核虛擬地址被4k大小的空閑區間隔,以防止越界-見以下圖。與進程虛擬地址的特性一樣,這些虛擬地址與物理內存沒有簡單的位移關系,必須通過內核頁表才可轉換為物理地址或物理頁。它們有可能尚未被映射,在發生缺頁時才真正分配物理頁面。這里給出一個小程序幫助大家認清上面幾種分配函數所對應的區域。includelinux/module.h includelinux/slab.h includelinux/vmalloc.h unsign
36、ed char*pagemem;unsigned char*kmallocmem;unsigned char*vmallocmem;int init_modulevoidpagemem=get_free_page0;printk"1 pagemem=%s",pagemem;kmallocmem=kmalloc100,0;printk"1 kmallocmem=%s",kmallocmem;vmallocmem=vmalloc 1000000;printk"1 vmallocmem=%s",vmallocmem;void cleanup
37、_modulevoidfree_pagepagemem;kfreekmallocmem;vfreevmallocmem;實例內存映射mmap是Linux操作系統的一個很大特色,它可以將系統內存映射到一個文件設備上,以便可以通過訪問文件內容來到達訪問內存的目的。這樣做的最大好處是進步了內存訪問速度,并且可以利用文件系統的接口編程設備在Linux中作為特殊文件處理訪問內存,降低了開發難度。許多設備驅動程序便是利用內存映射功能將用戶空間的一段地址關聯到設備內存上,無論何時,只要內存在分配的地址范圍內進展讀寫,實際上就是對設備內存的訪問。同時對設備文件的訪問也等同于對內存區域的訪問,也就是說,通過文件
38、操作接口可以訪問內存。Linux中的X效勞器就是一個利用內存映射到達直接高速訪問視頻卡內存的例子。熟悉文件操作的朋友一定會知道file_operations構造中有mmap方法,在用戶執行mmap系統調用時,便會調用該方法來通過文件訪問內存-不過在調用文件系統mmap方法前,內核還需要處理分配內存區域vma_struct、建立頁表等工作。對于詳細映射細節不作介紹了,需要強調的是,建立頁表可以采用remap_page_range方法一次建立起所有映射區的頁表,或利用vma_struct的nopage方法在缺頁時現場一頁一頁的建立頁表。第一種方法相比第二種方法簡單方便、速度快,但是靈敏性不高。一次調用所有頁表便定型了,不適用于那些需要現場建立頁表的場合-比方映射區需要擴展或下面我們例子中的情況。我們這里的實例希望利用內存映射,將系統內核中的一部分虛擬內存映射到用戶空間,以供給用程序讀取-你可利用它進展內核空間到用戶空間的大規模信息傳輸。因此我們將試圖寫一個虛擬字符設備驅動程序,通過它將系統內
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論