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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mmap映射大于4g的文件_浅谈mmap_刘伟

發布時間:2023/12/31 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mmap映射大于4g的文件_浅谈mmap_刘伟 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

奇技指南

作者說:最近在工作中遇到一個mmap使用相關的問題,造成了一定的困惑,于是花了些時間補了下 mmap的功課,在這里分享給大家,錯誤和不足之處大家多指教。

相關背景知識

  • 說到mmap的使用,我們首先要了解一下進程的虛擬進程地址空間的概念。Linux上為了作進程隔離,每個進程都運行在自己的單獨的虛擬進程空間,同時物理機上內存有限,每個進程使用虛擬內存地址來隔離又共享物理內存。我們平時在代碼里獲取的地址就是虛擬地址;
  • 放一張進程虛擬地址空間草圖,網上也可以很容易找到更精美的
  • 我們在程序中申請內存的操作,實際上只是在進程地址空間相應部分申請了一段虛擬地址,當實際對這段虛擬地址進行讀寫操作時,才會分配真正的物理內存;
  • 通常x86 Linux采用段頁式的內存管理模式,這塊不具體展開,簡單來說就是CPU訪問的邏輯地址,然后經過分段機制轉換成線性地址(你可以簡單理解成等價于上面說的虛擬地址),再經過分頁機制轉換成物理地址,第一次訪問的時候由于實現物理地址還沒有分配,會產生缺頁中斷來分配物理地址,用它來填充對應的頁表項;
  • 通過read系統調用來讀取磁盤上的文件時,文件內容會先被讀到內存的page cache部分,然后再從page cache中拷貝到應用層的讀緩存buffer中;對于打開的文件,內核都會在內存中維護一個inode結構體(對于同一個文件,即使被open多次,內核也僅維護這一個inode),其有一個成員是struct address_space*i_mapping , 它用來維護這個文件被讀取的所有部分在內存中的緩存,其使用xarray(全新封裝了基數樹的操作)來存儲這個物理頁(struct page), 如下圖:

mmap簡介

  • 先看原型:void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
  • 功能
  • 分配一塊新的連續的進程虛擬地址段(對應內核中的結構體就是 vm_area_struct)并返回其起始地址,如果給定了第一個參數,就優先從這個地址開始分配進程虛擬地址;
  • 如果提供了fd文件句枘,則映射文件內容到進程虛擬地址;
  • mmap的參數較多,其中prot和flags的可選項也比較多,具體大家可以使用 man命令查看;
  • mmap的幾種典型應用

    • 不同進程(可以是非父子進程)間共享映射
  • 這種情況需要借助磁盤文件,實際上是共享這個磁盤文件,將這個磁盤文件映射到各自的進程虛擬地址空間,但是其虛擬地址空間分頁轉換后其頁表項對應的物理內存是相同的;
  • 典型用法是需提供一個打開的文件句柄,使用 MAP_SHARED flag
  • int fd = open ("[filepath]", O_RDWR))void *addr = mmap (NULL, [mmaping length], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
    • 非子進程間通訊
  • 父進程使用 fork創建子進程,父子進程間可以使用mmap來通讀;
  • 典型用法是無需提供打開的文件句柄, 使用 MAP_SHARED | MAP_ANONYMOUS flag,
  • void *addr = mmap (NULL, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    • 進程通過 mmap 來讀寫文件
  • 從上面 相關背景知識 一節可知使用 read系統調用讀文件時,數據需經過 磁盤拷貝到page cache, page cache再拷貝到應用層緩存bufffer, 這兩個數據拷貝;
  • 使用 mmap 時,磁盤數據也是先讀到page cache中,然后會將mmap返回的虛擬地址最終對應的頁項表內容設定為和前面的page chache相同的物理頁, 這樣一來就免去了第二次的數據拷貝;
  • 用個示意圖來說明一下:
    • 用作glibc中malloc申請內存
  • 通常我們都說是通過調用 malloc來申請堆上內存,但實際上其內部實現使用了 brk和 mmap兩種系統調用,當申請的內存大于128K時,使用 mmap
  • 典型用法是無需提供打開的文件句柄, 使用 MAP_PRIVATE | MAP_ANONYMOUS flag
  • void *addr = mmap (NULL, buffer_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    • mmap的寫時拷貝
  • 如果我們在調用mmap時提供一個打開的文件句兩,但使用 MAP_PRIVATE的flags, 那這時對其的寫操作并不能真正修改對應的磁盤文件,它會作寫時拷貝,退化成匿名映射
  • mmap作磁盤文件映射時的特別說明

    • mmap映射的虛擬地址長度(即mmap的第二個參數)需要對齊到物理頁大小,在32位系統上通常是4K, 這一特點會導致一些有趣的事情發生,我們來看一下:假如一個文件的大小是5000Byte, 剛好比4K大一些,我們用mmap來從文件開始的位置來映射它,mmap的第二個參數給5000, 因為需要頁面對齊,實現映射的虛擬地址長度將是兩個4k,即8192, 8192 - 5000 = 3192的部分用0填充,也是可以被訪問到;
    • 如果用mmap映射某個文件時,這個文件大小為0, 不會分配任何的物理內存,也不能作任何的讀寫訪問;當向文件中寫入數據后,通過mmap返回的虛擬地址可以訪問這部分文件內容;

    mmap與內存換入換出

    • 由前面的介紹我們知道mmap不管是映射磁盤文件,還是作匿名映射,最終都會分配物理內存頁,因此這個物理內存頁在內存緊張時就有備換出的可能,當然mmap提供了MAP_LOCKED,可以鎖定內存不被換出,我們不考慮這種情況;
    • 如果使用mmap映射的是磁盤文件,其存在物理頁的內容會被清空,pte將記錄這種情況,再次需要訪問時,會重新讀取磁盤文件,緩存在page cache中;
    • 如果使用mmap作匿名映射,沒有相關聯的磁盤文件(或者使用MAP_PRIVATE方式映射磁盤文件),發生內存換出時,將被交換到swap中,swap實際上也對應著磁盤塊,最終也是寫在磁盤上;

    關于360技術:360技術是360技術團隊打造的技術分享公眾號,每天推送技術干貨內容,更多技術信息歡迎關注“360技術”微信公眾號

    總結

    以上是生活随笔為你收集整理的mmap映射大于4g的文件_浅谈mmap_刘伟的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。