共享內存與存儲映射(mmap)


    【前言】對這兩個理解還是不夠深刻,寫一篇博客來記錄一下。

  首先關於共享內存的鏈接:共享內存里面包含了創建共享內存區域的函數,以及兩個進程怎么掛載共享內存通信,分離、釋放共享內存。

  共享內存的好處就是效率高,不需要太多次的進行數據的copy。可以直接進行讀寫內存。所以,相對來說在IPC進程間通信三大主題里面,共享內存要比消息隊列使用多,而且消息隊列只在有血緣關系的進程間通信;但是,共享內存不保證同步,使用了信號量用來保證共享內存同步。Linux中的兩種共享內存。一種是我們的IPC通信System V版本的共享內存,另外的一種就是我們今天提到的存儲映射I/O(mmap函數),當然還有一種POSIX的共享內存,它是在mmap基礎之上構建的。

一、mmap

  mmap I/O的描述符間接說明內存映射是對文件操作。另外,mmap另外可以在無親緣的進程之間提供共享內存區。這樣,類似的兩個進程之間就是可以進行了通信。

  Linux提供了內存映射函數mmap, 它把文件內容映射到一段內存上(准確說是虛擬內存上,運行着進程), 通過對這段內存的讀取和修改, 實現對文件的讀取和修改。mmap()系統調用使得進程之間可以通過映射一個普通的文件實現共享內存。普通文件映射到進程地址空間后,進程可以像訪問內存的方式對文件進行訪問,不需要其他內核態的系統調用(read,write)去操作。

  這里是講設備或者硬盤存儲的一塊空間映射到物理內存,然后操作這塊物理內存就是在操作實際的硬盤空間,不需要經過內核態傳遞。比如你的硬盤上有一個文件,你可以使用linux系統提供的mmap接口,將這個文件映射到進程一塊虛擬地址空間,這塊空間會對應一塊物理內存,當你讀寫這塊物理空間的時候,就是在讀取實際的磁盤文件,就是這么直接高效。通常諸如共享庫的加載都是通過內存映射的方式加載到物理內存的

  mmap系統調用並不完全是為了共享內存來設計的,它本身提供了不同於一般對普通文件的訪問的方式,進程可以像讀寫內存一樣對普通文件進行操作,IPC的共享內存是純粹為了共享。

  (1)mmap系統調用介紹:

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

  這就是mmap系統調用的接口,mmap函數成功返回指向內存區域的指針,失敗返回MAP_FAILED。

  addr,某個特定的地址作為起始地址,當被設置為NULL,標識系統自動分配地址。實實在在的物理區域。

  length說的是內存段的長度。

  prot是用來設定內存段的訪問權限。

prot參數 說明
PROT_READ 內存段可讀
PROT_WRITE 內存段可寫
PROT_EXEC 內存段可執行
PROT_NONE 內存段不能被訪問

  flags參數控制內存段內容被修改以后程序的行為。

flags參數 說明
MAP_SHARED 進程間共享內存,對該內存段修改反映到映射文件中。提供了POSIX共享內存
MAP_PRIVATE 內存段為調用進程所私有。對該內存段的修改不會反映到映射文件
MAP_ANNOYMOUS 這段內存不是從文件映射而來的。內容被初始化為全0
MAP_FIXED 內存段必須位於start參數指定的地址處,start必須是頁大小的整數倍(4K整數倍)
MAP_HUGETLB 按照大內存頁面來分配內存空間

  fd參數是用來被映射文件對應的文件描述符。通過open系統調用得到。

  offset設定從何處進行映射。

(2)mmap用於共享內存的方式

  1、我們可以使用普通文件進行提供內存映射,例如,open系統調用打開一個文件,然后進行mmap操作,得到共享內存,這種方式適用於任何進程之間。

  2、可以使用特殊文件進行匿名內存映射,這個相對的是具有血緣關系的進程之間,當父進程調用mmap,然后進行fork,這樣父進程創建的子進程會繼承父進程匿名映射后的地址空間,這樣,父子進程之間就可以進行通信了。相當於是mmap的返回地址此時是父子進程同時來維護。

  3、另外POSIX版本的共享內存底層也是使用了mmap。所以,共享內存在在posix上一定程度上就是指的內存映射了。https://www.cnblogs.com/LubinLew/p/POSIX-shared_memory.html

三、mmap和System V共享內存的比較

共享內存:

![enter description here][1]

這是System V版本的共享內存(以下我們統稱為shm),下面看下mmap的:
![enter description here][2]

總結:

  1、mmap是在磁盤上建立一個文件,每個進程地址空間中開辟出一塊空間進行映射。而shm共享內存,每個進程最終會映射到同一塊物理內存。shm保存在物理內存,這樣讀寫的速度肯定要比磁盤要快,但是存儲量不是特別大。

  2、相對於shm來說,mmap更加簡單,調用更加方便,所以這也是大家都喜歡用的原因。

  3、另外mmap有一個好處是當機器重啟,因為mmap把文件保存在磁盤上,這個文件還保存了操作系統同步的映像,所以mmap不會丟失,但是shmget在內存里面就會丟失。

  4、總之,共享內存是在內存中創建空間,每個進程映射到此處。內存映射是創建一個文件,並且映射到每個進程開辟的空間中。

      但在posix中的共享內存就是指這種使用文件的方式“內存映射”。參考:https://www.cnblogs.com/LubinLew/p/POSIX-shared_memory.html

附錄:linux高端內存https://www.cnblogs.com/wuchanming/p/4360277.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM