MMAP使用(一、基本接口)

提問:

  1. mmap是什麼?有什麼用?
  2. mmap的接口怎麼使用?每個參數又有什麼作用?

回答:

1.mmap是什麼?有什麼用?

  1. mmap將一個文件或者其它對象映射進內存。mmap操作提供了一種機制,讓用戶程序直接訪問設備內存,這種機制,相比較在用戶空間內核空間互相拷貝數據,效率更高。在要求高性能的應用中比較常用。mmap映射內存必須是頁面大小的整數倍,面向流的設備不能進行mmap,mmap的實現和硬件有關。
  2. 兩個進程可以通過映射普通文件實現共享內存通信。
  3. 在網絡下載中,可以通過映射整個文件,使文件減少一次從內核態到用戶態的拷貝,從而加快傳輸的效率。

2.mmap的接口怎麼使用?每個參數又有什麼作用?

mmap的建立

#include<sys/mman.h>

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

mmap()系統調用在調用進程的虛擬地址空間中創建一個新的映射。
成功返回映射首地址,這地址分頁對齊,失敗返回MAP_FAILED(在Linux實現上等同於(void*)-1)。

參數addr指定了映射被放置的虛擬地址。首選做法是將addr指定爲NULL,內核會爲映射選擇一個合適的地址。
        將addr指定爲非NULL,內核會將該參數值作爲一個提示信息來處理。

參數length指定了映射字節數。如果length不是分頁的整數倍,內核會以分頁大小爲單位建立映射。
         因此,length實際上會被向上提升爲分頁大小的下一個倍數。

參數prot和參數flags在MMAP使用二中介紹。這裏只介紹它們的用處。
參數prot是一個位掩碼,指定了新內存映射上的保護信息。
參數flags是一個控制映射操作各個方面的選項的位掩碼。只能選一個。

(匿名映射會忽略下面兩個參數)
參數fd表示映射的文件的文件描述符。

參數offset指定了映射在文件中的起點,必須是系統分頁大小的倍數。

解除映射區域:munmap()

#include<sys/mman.h>

int munmap(void *addr, size_t length);

成功返回0,失敗返回-1.
參數addr是待解除映射地址範圍的起始地址,它必須與一個分頁邊界對齊。
參數length是一個非負整數,指定了待解除映射區域的大小(字節數)。
        範圍爲系統分頁大小的下一個倍數的地址空間將會被解除映射。
  • 一般來講,通常會解除整個映射。因此可以將addr指定爲上一個mmap()調用返回的地址,並且length值與mmap()調用中使用的length值一樣。
int fd = open(fileName, O_RDWR | O_CREAT, 0666);
if(-1 == fd)
{
    perror("open");
    return -1;
}
int length = 1;
char *addr = (char*)mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
if(addr == MAP_FAILED)
{
    perror("mmap");
    return -1;
}

if(munmap(addr, length) == -1)
{
    perror("munmap");
    return -1;
}

 

同步映射區域:msync()

int msync(void *addr, size_t length, int flags);

讓應用程序能夠顯式地控制何時完成共享映射與映射文件之間的同步。
這是非常有用的。如爲確保數據完整性。
成功返回0,失敗返回-1.
傳給msync()的addr和length參數指定了需同步的內存區域的起始地址和大小。
在addr中指定的地址必須是分頁對齊的,length會向上舍入到系統分頁的下一個整數倍大小。

參數flags可取值爲下列值中的一個:
MS_SYNC: 執行一個同步的文件寫入。這個調用會阻塞直到內存區域中所有被修改過的分頁被寫入到底盤爲止。
MS_ASYNC:執行一個異步的文件寫入。內存區域中被修改過的分頁會在後面某個時刻被寫入磁盤並立即對在相應文件區域中執行read()
的其他進程可見。

flags參數中還可以加上下面這個值。
MS_INVALIDATE:使映射數據的緩存副本失效。
當內存區域中所有被修改過的分頁被同步到文件中之後,內存區域中所有與底層文件不一致的分頁會被標記爲無效。
當下次引用這些分頁會從文件的相應位置處複製相應的分頁內容。
其結果是其他進程對文件作出的所有更新將會在內存區域中可見。

3.Mmap使用細節

  1. mmap中參數length大小可以超過文件大小,當然無論超不超過都會提升至系統頁的整數倍大小。但是如果寫入的內容超過了文件大小,超過部分不會寫入文件。這時候就需要配合ftruncate或者lseek對文件進行偏移(相關概念:文件空洞)。代碼如下:(文件在一開始只有6B的空間,如果不配合ftruncate或者lseek,後面"is null"不會寫入文件中)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章