Linux C++內存映射方式讀寫文件

內存映射就是將磁盤上的文件映射到系統內存中,對內存的修改可以同步到對磁盤文件的修改。可以對大數據文件處理,並且可以提高文件的讀寫速度。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<stdio.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<unistd.h>
#include<fcntl.h>
#define NumReconds 100
typedef struct
{
    int iNum;
    char sName[24];
} Recond;
int main(void)
{
                                                                                                                                                                
    Recond recond,*mapped;
    int i,f;
    FILE *fp;
                                                                                                                                                                
    fp=fopen("recond.dat","w+");
    for( i=0; i < NumReconds; i++)
    {
        recond.iNum = i;
        sprintf(recond.sName,"Recond-%d\n",i);
        fwrite(&recond,sizeof(Recond),1,fp);
    
                                                                                                                                                                
    fclose(fp);
        //使用傳統方式修改文件內容
    fp = fopen("recond.dat","r+");
    //獲得要修改文件的位置
        fseek(fp,43*sizeof(recond),SEEK_SET);
    fread(&recond,sizeof(recond),1,fp);
    recond.iNum = 143;
    sprintf(recond.sName,"Recond-%d",recond.iNum);
    fwrite(&recond,sizeof(recond),1,fp);
    fclose(fp);
        //使用內存映射的方式打開文件,修改文件內存
    //注意這裏是open打開不是fopen!!!!  
    f = open("recond.dat",O_RDWR);
        //獲得磁盤文件的內存映射
    mapped = (Recond *) mmap(0 , NumReconds * sizeof(Recond) , PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
    mapped[43].iNum = 999;
        sprintf(mapped[43].sName,"Recond-%d",mapped[43].iNum);
        //將修改同步到磁盤中
    msync((void *)mapped,NumReconds*sizeof(recond),MS_ASYNC);
        //關閉內存映射
    munmap((void *)mapped,NumReconds*sizeof(recond));
    close(f);
    exit(0);
}




void *mmap(void *start, size_t length, int prot, int flags,

int fd, off_t offset);

返回值:
     若映射成功則返回映射區的內存起始地址

參數說明:

start:映射區的開始地址,設置爲0時表示由系統決定映射區的起始地址。
length:映射區的長度。//長度單位是 以字節爲單位,不足一內存頁按一內存頁處理
prot:期望的內存保護標誌,不能與文件的打開模式衝突。是以下的某個值,可以通過or運算合理地組合在一起
               PROT_EXEC //頁內容可以被執行
               PROT_READ //頁內容可以被讀取
               PROT_WRITE //頁可以被寫入    
               PROT_NONE //頁不可訪問

flags:指定映射對象的類型,映射選項和映射頁是否可以共享。它的值可以是一個或者多個以下位的組合體

           MAP_FIXED //使用指定的映射起始地址,如果由start和len參數指定的內存區重疊於現存    映射空間,重疊部分將會被丟棄。如果指定的起始地址不可用,操作將會失敗。並且起始地 址必須落在頁的邊界上。
MAP_SHARED //與其它所有映射這個對象的進程共享映射空間。對共享區的寫入,相當於輸出到文件。直到msync()或者munmap()被調用,文件實際上不會被更新。
MAP_PRIVATE //建立一個寫入時拷貝的私有映射。內存區域的寫入不會影響到原文件。這個標誌和以上標誌是互斥的,只能使用其中一個。
MAP_DENYWRITE //這個標誌被忽略。

MAP_EXECUTABLE //同上


fd:有效的文件描述詞。一般是由open()函數返回,其值也可以設置爲-1,此時需要指定flags參數中的MAP_ANON,表明進行的是匿名映射。


offset:被映射對象內容的起點。




int msync ( void * addr, size_t len, int flags)

進程在映射空間的對共享內容的改變並不直接寫回到磁盤文件中,往往在調用munmap()後才執行該操作。

可以通過調用msync()函數來實現磁盤文件內容與共享內存區中的內容一致,即同步操作.


addr:文件映射到進程空間的地址;

len:映射空間的大小;

flags:刷新的參數設置,可以取值MS_ASYNC/ MS_SYNC/ MS_INVALIDATE
其中:
取值爲MS_ASYNC(異步)時,調用會立即返回,不等到更新的完成;
取值爲MS_SYNC(同步)時,調用會等到更新完成之後返回;

取MS_INVALIDATE(通知使用該共享區域的進程,數據已經改變)時,在共享內容更改之後,使得文件的其他映射失效,從而使得共享該文件的其他進程去重新獲取最新值;




int munmap(void *start,size_t length);

函數說明 munmap()用來取消參數start所指的映射內存起始地址,參數length則是欲取消的內存大小。

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