华南俳烁实业有限公司

考試首頁 | 考試用書 | 培訓(xùn)課程 | 模擬考場 | 考試論壇  
  當(dāng)前位置:操作系統(tǒng) > Unix > 文章內(nèi)容
  

Linux內(nèi)存管理之mmap詳解:mmap進(jìn)行內(nèi)存映射的原理

 [ 2017年1月21日 ] 【

mmap進(jìn)行內(nèi)存映射的原理

     mmap系統(tǒng)調(diào)用的最終目的是將,設(shè)備或文件映射到用戶進(jìn)程的虛擬地址空間,實現(xiàn)用戶進(jìn)程對文件的直接讀寫,這個任務(wù)可以分為以下三步:

1.在用戶虛擬地址空間中尋找空閑的滿足要求的一段連續(xù)的虛擬地址空間,為映射做準(zhǔn)備(由內(nèi)核mmap系統(tǒng)調(diào)用完成)

       每個進(jìn)程擁有3G字節(jié)的用戶虛存空間。但是,這并不意味著用戶進(jìn)程在這3G的范圍內(nèi)可以任意使用,因為虛存空間最終得映射到某個物理存儲空間(內(nèi)存或磁盤空間),才真正可以使用。

       那么,內(nèi)核怎樣管理每個進(jìn)程3G的虛存空間呢?概括地說,用戶進(jìn)程經(jīng)過編譯、鏈接后形成的映象文件有一個代碼段和數(shù)據(jù)段(包括data段和bss段),其中代碼段在下,數(shù)據(jù)段在上。數(shù)據(jù)段中包括了所有靜態(tài)分配的數(shù)據(jù)空間,即全局變量和所有申明為static的局部變量,這些空間是進(jìn)程所必需的基本要求,這些空間是在建立一個進(jìn)程的運(yùn)行映像時就分配好的。除此之外,堆棧使用的空間也屬于基本要求,所以也是在建立進(jìn)程時就分配好的,如圖3.1所示:

 

 

 圖3.1  進(jìn)程虛擬空間的劃分

      在內(nèi)核中,這樣每個區(qū)域用一個結(jié)構(gòu)struct vm_area_struct 來表示.它描述的是一段連續(xù)的、具有相同訪問屬性的虛存空間,該虛存空間的大小為物理內(nèi)存頁面的整數(shù)倍。可以使用 cat /proc//maps來查看一個進(jìn)程的內(nèi)存使用情況,pid是進(jìn)程號.其中顯示的每一行對應(yīng)進(jìn)程的一個vm_area_struct結(jié)構(gòu).

下面是struct vm_area_struct結(jié)構(gòu)體的定義:

  1. #include <linux/mm_types.h>

  2. /* This struct defines a memory VMM memory area. */

  3. struct vm_area_struct {
  4. struct mm_struct * vm_mm; /* VM area parameters */
  5. unsigned long vm_start;
  6. unsigned long vm_end;

  7. /* linked list of VM areas per task, sorted by address */
  8. struct vm_area_struct *vm_next;
  9. pgprot_t vm_page_prot;
  10. unsigned long vm_flags;

  11. /* AVL tree of VM areas per task, sorted by address */
  12. short vm_avl_height;
  13. struct vm_area_struct * vm_avl_left;
  14. struct vm_area_struct * vm_avl_right;

  15. /* For areas with an address space and backing store,
  16. vm_area_struct *vm_next_share;
  17. struct vm_area_struct **vm_pprev_share;
  18. struct vm_operations_struct * vm_ops;
  19. unsigned long vm_pgoff; /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */
  20. struct file * vm_file;
  21. unsigned long vm_raend;
  22. void * vm_private_data; /* was vm_pte (shared mem) */
  23. };

      通常,進(jìn)程所使用到的虛存空間不連續(xù),且各部分虛存空間的訪問屬性也可能不同。所以一個進(jìn)程的虛存空間需要多個vm_area_struct結(jié)構(gòu)來描述。在vm_area_struct結(jié)構(gòu)的數(shù)目較少的時候,各個vm_area_struct按照升序排序,以單鏈表的形式組織數(shù)據(jù)(通過vm_next指針指向下一個vm_area_struct結(jié)構(gòu))。但是當(dāng)vm_area_struct結(jié)構(gòu)的數(shù)據(jù)較多的時候,仍然采用鏈表組織的化,勢必會影響到它的搜索速度。針對這個問題,vm_area_struct還添加了vm_avl_hight(樹高)、vm_avl_left(左子節(jié)點(diǎn))、vm_avl_right(右子節(jié)點(diǎn))三個成員來實現(xiàn)AVL樹,以提高vm_area_struct的搜索速度。

  假如該vm_area_struct描述的是一個文件映射的虛存空間,成員vm_file便指向被映射的文件的file結(jié)構(gòu),vm_pgoff是該虛存空間起始地址在vm_file文件里面的文件偏移,單位為物理頁面。

圖3.2  進(jìn)程虛擬地址示意圖 

因此,mmap系統(tǒng)調(diào)用所完成的工作就是準(zhǔn)備這樣一段虛存空間,并建立vm_area_struct結(jié)構(gòu)體,將其傳給具體的設(shè)備驅(qū)動程序.

2. 建立虛擬地址空間和文件或設(shè)備的物理地址之間的映射(設(shè)備驅(qū)動完成)

  建立文件映射的第二步就是建立虛擬地址和具體的物理地址之間的映射,這是通過修改進(jìn)程頁表來實現(xiàn)的.mmap方法是file_opeartions結(jié)構(gòu)的成員:

  int (*mmap)(struct file *,struct vm_area_struct *);


linux有2個方法建立頁表:

(1) 使用remap_pfn_range一次建立所有頁表.

   int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long pfn, unsigned long size, pgprot_t prot); 

返回值:

成功返回 0, 失敗返回一個負(fù)的錯誤值
參數(shù)說明:

vma 用戶進(jìn)程創(chuàng)建一個vma區(qū)域


virt_addr 重新映射應(yīng)當(dāng)開始的用戶虛擬地址. 這個函數(shù)建立頁表為這個虛擬地址范圍從 virt_addr 到 virt_addr_size.


pfn 頁幀號, 對應(yīng)虛擬地址應(yīng)當(dāng)被映射的物理地址. 這個頁幀號簡單地是物理地址右移 PAGE_SHIFT 位. 對大部分使用, VMA 結(jié)構(gòu)的 vm_paoff 成員正好包含你需要的值. 這個函數(shù)影響物理地址從 (pfn<


size 正在被重新映射的區(qū)的大小, 以字節(jié).


prot 給新 VMA 要求的"protection". 驅(qū)動可(并且應(yīng)當(dāng))使用在vma->vm_page_prot 中找到的值.

(2) 使用nopage VMA方法每次建立一個頁表項.

   struct page *(*nopage)(struct vm_area_struct *vma, unsigned long address, int *type);

返回值:

成功則返回一個有效映射頁,失敗返回NULL.

參數(shù)說明:

address 代表從用戶空間傳過來的用戶空間虛擬地址.

返回一個有效映射頁.


(3) 使用方面的限制:

remap_pfn_range不能映射常規(guī)內(nèi)存,只存取保留頁和在物理內(nèi)存頂之上的物理地址。因為保留頁和在物理內(nèi)存頂之上的物理地址內(nèi)存管理系統(tǒng)的各個子模塊管理不到。640 KB 和 1MB 是保留頁可能映射,設(shè)備I/O內(nèi)存也可以映射。如果想把kmalloc()申請的內(nèi)存映射到用戶空間,則可以通過mem_map_reserve()把相應(yīng)的內(nèi)存設(shè)置為保留后就可以。

3. 當(dāng)實際訪問新映射的頁面時的操作(由缺頁中斷完成)

(1)  page cache及swap cache中頁面的區(qū)分:一個被訪問文件的物理頁面都駐留在page cache或swap cache中,一個頁面的所有信息由struct page來描述。struct page中有一個域為指針mapping ,它指向一個struct address_space類型結(jié)構(gòu)。page cache或swap cache中的所有頁面就是根據(jù)address_space結(jié)構(gòu)以及一個偏移量來區(qū)分的。

 

(2) 文件與 address_space結(jié)構(gòu)的對應(yīng):一個具體的文件在打開后,內(nèi)核會在內(nèi)存中為之建立一個struct inode結(jié)構(gòu),其中的i_mapping域指向一個address_space結(jié)構(gòu)。這樣,一個文件就對應(yīng)一個address_space結(jié)構(gòu),一個 address_space與一個偏移量能夠確定一個page cache 或swap cache中的一個頁面。因此,當(dāng)要尋址某個數(shù)據(jù)時,很容易根據(jù)給定的文件及數(shù)據(jù)在文件內(nèi)的偏移量而找到相應(yīng)的頁面。 

(3) 進(jìn)程調(diào)用mmap()時,只是在進(jìn)程空間內(nèi)新增了一塊相應(yīng)大小的緩沖區(qū),并設(shè)置了相應(yīng)的訪問標(biāo)識,但并沒有建立進(jìn)程空間到物理頁面的映射。因此,第一次訪問該空間時,會引發(fā)一個缺頁異常。 


(4) 對于共享內(nèi)存映射情況,缺頁異常處理程序首先在swap cache中尋找目標(biāo)頁(符合address_space以及偏移量的物理頁),如果找到,則直接返回地址;如果沒有找到,則判斷該頁是否在交換區(qū) (swap area),如果在,則執(zhí)行一個換入操作;如果上述兩種情況都不滿足,處理程序?qū)⒎峙湫碌奈锢眄撁,并把它插入到page cache中。進(jìn)程最終將更新進(jìn)程頁表。 

     注:對于映射普通文件情況(非共享映射),缺頁異常處理程序首先會在page cache中根據(jù)address_space以及數(shù)據(jù)偏移量尋找相應(yīng)的頁面。如果沒有找到,則說明文件數(shù)據(jù)還沒有讀入內(nèi)存,處理程序會從磁盤讀入相應(yīng)的頁面,并返回相應(yīng)地址,同時,進(jìn)程頁表也會更新.


(5) 所有進(jìn)程在映射同一個共享內(nèi)存區(qū)域時,情況都一樣,在建立線性地址與物理地址之間的映射之后,不論進(jìn)程各自的返回地址如何,實際訪問的必然是同一個共享內(nèi)存區(qū)域?qū)?yīng)的物理頁面。  

本文糾錯】【告訴好友】【打印此文】【返回頂部
將考試網(wǎng)添加到收藏夾 | 每次上網(wǎng)自動訪問考試網(wǎng) | 復(fù)制本頁地址,傳給QQ/MSN上的好友 | 申請鏈接 | 意見留言 TOP
關(guān)于本站  網(wǎng)站聲明  廣告服務(wù)  聯(lián)系方式  站內(nèi)導(dǎo)航  考試論壇
Copyright © 2007-2013 中華考試網(wǎng)(Examw.com) All Rights Reserved
东兰县| 潼关县| 普宁市| 洪湖市| 华坪县| 杭锦旗| 云梦县| 嘉黎县| 丹凤县| 天等县| 萨嘎县| 富民县| 黑山县| 贺州市| 张家口市| 洛南县| 缙云县| 泽普县| 柘城县| 襄垣县| 广饶县| 高雄县| 顺平县| 茶陵县| 五峰| 井冈山市| 绥德县| 盐池县| 关岭| 秦安县| 沙湾县| 华安县| 凭祥市| 红河县| 鄂温| 鄢陵县| 苏尼特左旗| 渝中区| 姜堰市| 炎陵县| 新闻|