日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mmap内存映射学习笔记

發(fā)布時間:2024/4/15 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mmap内存映射学习笔记 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1、進(jìn)行虛擬內(nèi)存結(jié)構(gòu)體

  前文《虛擬內(nèi)存管理》我們講到每個進(jìn)程的結(jié)構(gòu)體task_struct中都有一個內(nèi)存描述結(jié)構(gòu)體mm_struct。 mm_struct此結(jié)構(gòu)體描述了進(jìn)程占用虛擬內(nèi)存的情況,包含每個內(nèi)存段的起始地址、結(jié)束地址。

  如下圖,除了固定的代碼段、數(shù)據(jù)段、BSS段、堆、棧,還有一個MMAP 段,此段為程序員自己通過mmap()函數(shù)主動生成的一個段,用于將磁盤文檔映射到內(nèi)存中以增加文件訪問效率(也可進(jìn)行進(jìn)程通信)的一種手段。

  上述每個段都會生成一個VMA結(jié)構(gòu)體。

2、mmap()的使用方法

  void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

  start :? 指向欲映射的內(nèi)存起始地址,通常設(shè)為 NULL,代表讓系統(tǒng)自動選定地址,映射成功后返回該地址。

? ?length:? 代表將文件中多大的部分映射到內(nèi)存。

? ?prot? :? 映射區(qū)域的保護(hù)方式。可以為以下幾種方式的組合:

? ? ? ? PROT_EXEC 映射區(qū)域可被執(zhí)行

? ? ? ? PROT_READ 映射區(qū)域可被讀取

? ? ? ? PROT_WRITE 映射區(qū)域可被寫入

? ? ? ? PROT_NONE 映射區(qū)域不能存取——需要小于等于文件打開的權(quán)限一致

? ?flags :? 影響映射區(qū)域的各種特性。在調(diào)用mmap()時必須要指定MAP_SHARED 或MAP_PRIVATE。

? ? ? ? MAP_FIXED 如果參數(shù)start所指的地址無法成功建立映射時,則放棄映射,不對地址做修正。通常不鼓勵用此旗標(biāo)。

? ? ? ? MAP_SHARED 對映射區(qū)域的寫入數(shù)據(jù)會復(fù)制回文件內(nèi),而且允許其他映射該文件的進(jìn)程共享。

? ? ? ? MAP_PRIVATE 對映射區(qū)域的寫入操作會產(chǎn)生一個映射文件的復(fù)制,即私人的“寫入時復(fù)制”(copy on write)對此區(qū)域作的任何修改都不會寫回原來的文件內(nèi)容。

? ? ? ? MAP_ANONYMOUS建立匿名映射。此時會忽略參數(shù)fd,不涉及文件,而且映射區(qū)域無法和其他進(jìn)程共享。

? ? ? ? MAP_DENYWRITE只允許對映射區(qū)域的寫入操作,其他對文件直接寫入的操作將會被拒絕。

? ? ? ? MAP_LOCKED 將映射區(qū)域鎖定住,這表示該區(qū)域不會被置換(swap)。

? ?fd? ? :? 要映射到內(nèi)存中的文件描述符。如果使用匿名內(nèi)存映射時,即flags中設(shè)置了MAP_ANONYMOUS,fd設(shè)為-1。有些系統(tǒng)不支持匿名內(nèi)存映射,則可以使用fopen打開/dev/zero文件,然后對該文件進(jìn)行映射,可以同樣達(dá)到匿名內(nèi)存映射的效果。

? ?offset:文件映射的偏移量,通常設(shè)置為0,代表從文件最前方開始對應(yīng),offset必須是PAGE_SIZE的整數(shù)倍。

返回值:若映射成功則返回映射區(qū)的內(nèi)存起始地址,否則返回MAP_FAILED(-1),錯誤原因存于errno 中。

int munmap(void *start, size_t length);——解除mmap的映射

int msync ( void * addr , size_t len, int flags);? ——文件回寫

3、mmap()的作用,將文件或者其他對象映射到內(nèi)存中,使文件操作像通過指針操作內(nèi)存一樣簡單快速

  其主要有兩個用途,下面我們就從這兩個方面來講述:

  • 內(nèi)存映射
  • 進(jìn)程通信

4、內(nèi)存映射,傳統(tǒng)文件訪問緩慢,內(nèi)存映射后操作文件速度加快

  傳統(tǒng)文件訪問的缺點(diǎn):

  • 效率低:應(yīng)用程序通過read,write,ioctl來訪問硬件設(shè)備,它們都要經(jīng)過兩次的數(shù)據(jù)拷貝,一次是用戶空間和內(nèi)核空間的數(shù)據(jù)拷貝,另外一次是內(nèi)核空間和硬件之間的數(shù)據(jù)拷貝。
  • 浪費(fèi)空間: 訪問文件的傳統(tǒng)方法是用open打開它們, 如果有多個進(jìn)程訪問同一個文件, 則每一個進(jìn)程在自己的地址空間都包含有該文件的副本,這不必要地浪費(fèi)了存儲空間.??

    下圖說明了兩個進(jìn)程同時讀一個文件的同一頁的情形. 系統(tǒng)要將該頁從磁盤讀到高速緩沖區(qū)中, 每個進(jìn)程再執(zhí)行一個存儲器內(nèi)的復(fù)制操作將數(shù)據(jù)從高速緩沖區(qū)讀到自己的地址空間.?

  

  

通過將磁盤文件映射到內(nèi)存中,從而使文件訪問更加高效簡單:
  眾多內(nèi)存數(shù)據(jù)庫如MongoDB操作數(shù)據(jù),就是把文件磁盤內(nèi)容映射到內(nèi)存中進(jìn)行處理

5、共享內(nèi)存實(shí)現(xiàn)進(jìn)行通信

進(jìn)程A和進(jìn)程B都將該頁映射到自己的地址空間, 當(dāng)進(jìn)程A第一次訪問該頁中的數(shù)據(jù)時, 它生成一個缺頁中斷. 內(nèi)核此時讀入這一頁到內(nèi)存并更新頁表使之指向它.以后,

當(dāng)進(jìn)程B訪問同一頁面而出現(xiàn)缺頁中斷時, 該頁已經(jīng)在內(nèi)存, 內(nèi)核只需要將進(jìn)程B的頁表登記項(xiàng)指向次頁即可。

6、共享內(nèi)存比管道的優(yōu)勢:共享內(nèi)存比管道和消息隊(duì)列效率高

  共享內(nèi)存和消息隊(duì)列,FIFO,管道傳遞消息的區(qū)別:
  ——消息隊(duì)列,FIFO,管道的消息傳遞方式一般為
    1:服務(wù)器得到輸入
    2:通過管道,消息隊(duì)列寫入數(shù)據(jù),通常需要從進(jìn)程拷貝到內(nèi)核。
    3:客戶從內(nèi)核拷貝到進(jìn)程
    4:然后再從進(jìn)程中拷貝到輸出文件
  上述過程通常要經(jīng)過4次拷貝,才能完成文件的傳遞。
  ——共享內(nèi)存只需要
    1:從輸入文件到共享內(nèi)存區(qū)
    2:從共享內(nèi)存區(qū)輸出到文件

下面是舉例:

7、mmap注意事項(xiàng)

?

?最終被映射文件的內(nèi)容的長度不會超過文件本身的初始大小,即映射不能改變文件的大小。文件被映射部分而不是整個文件決定了進(jìn)程能夠訪問的空間大小

?8、mmap的實(shí)現(xiàn)

  • 映射時,在虛擬地址空間中為你創(chuàng)建虛擬映射區(qū)域

    進(jìn)程在用戶空間調(diào)用庫函數(shù)mmap

    在當(dāng)前進(jìn)程的虛擬地址空間中,尋找一段空閑的滿足要求的連續(xù)的虛擬地址
    為此虛擬區(qū)分配一個vm_area_struct結(jié)構(gòu),接著對這個結(jié)構(gòu)的各個域進(jìn)行了初始化

  • 調(diào)用內(nèi)核空間的系統(tǒng)調(diào)用函數(shù)mmap,實(shí)現(xiàn)文件物理地址和進(jìn)程虛擬地址的一一映射關(guān)系

    完成以上兩部后,這片虛擬地址并沒有任何數(shù)據(jù)關(guān)聯(lián)到主存中。

  • 進(jìn)程發(fā)起對這片映射空間的訪問,引發(fā)缺頁異常,實(shí)現(xiàn)文件內(nèi)容到物理內(nèi)存(主存)的拷貝

  進(jìn)程的讀或?qū)懖僮髟L問虛擬地址空間這一段映射地址,通過查詢頁表,
    發(fā)現(xiàn)這一段地址并不在物理頁面上。因?yàn)槟壳爸唤⒘说刂酚成?#xff0c;真正
    的硬盤數(shù)據(jù)還沒有拷貝到內(nèi)存中,因此引發(fā)缺頁異常。處理缺頁異常時
    發(fā)現(xiàn)對于的數(shù)據(jù)還沒有寫入內(nèi)存,于是會將文件數(shù)據(jù)換入內(nèi)存。
  調(diào)頁過程先在交換緩存空間(swap cache)中尋找需要訪問的內(nèi)存頁,如
    果沒有則調(diào)用nopage函數(shù)把所缺的頁從磁盤裝入到主存中

?

轉(zhuǎn)載于:https://www.cnblogs.com/tjyuanxi/p/9394387.html

總結(jié)

以上是生活随笔為你收集整理的mmap内存映射学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。