Linux 檔案對映虛擬記憶體操作

2022-09-19 23:15:21 字數 3681 閱讀 1588

目錄

把硬碟資料搬到記憶體中去操作的方式被稱為檔案對映虛擬記憶體,由於記憶體訪問的特殊性,資料到了記憶體後可提高訪問和操作的速率。

標頭檔案

函式原型

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

int munmap(void* start,size_t length);

對映條件

mmap()必須以page_size為單位進行對映,而記憶體也只能以頁為單位進行對映,若要對映非page_size整數倍的位址範圍,要先進行記憶體對齊,強行以page_size的倍數大小進行對映。

引數說明

length:對映區的長度,長度單位是 以位元組為單位,不足一記憶體頁按一記憶體頁處理

prot:期望的記憶體保護標誌,不能與檔案的開啟模式衝突。是以下的某個值,可以通過按位或運算合理地組合在一起

prot_exec //頁內容可以被執行

prot_read //頁內容可以被讀取

prot_write //頁可以被寫入

prot_none //頁不可訪問

flags:指定對映物件的型別,對映選項和對映頁是否可以共享。它的值可以是乙個或者多個以下位的組合體

map_fixed //使用指定的對映起始位址,如果由start和len引數指定的記憶體區重疊於現存的對映空間,重疊部分將會被丟棄。如果指定的起始位址不可用,操作將會失敗。並且起始位址必須落在頁的邊界上。

map_shared //與其它所有對映這個物件的程序共享對映空間。對共享區的寫入,相當於輸出到檔案。直到msync()或者munmap()被呼叫,檔案實際上不會被更新。

map_private //建立乙個寫入時拷貝的私有對映。記憶體區域的寫入不會影響到原檔案。這個標誌和以上標誌是互斥的,只能使用其中乙個。

map_denywrite //這個標誌被忽略。

map_executable //同上

map_noreserve //不要為這個對映保留交換空間。當交換空間被保留,對對映區修改的可能會得到保證。當交換空間不被保留,同時記憶體不足,對對映區的修改會引起段違例訊號。

map_locked //鎖定對映區的頁面,從而防止頁面被交換出記憶體。

map_growsdown //用於堆疊,告訴核心vm系統,對映區可以向下擴充套件。

map_anonymous //匿名對映,對映區不與任何檔案關聯。

map_anon //map_anonymous的別稱,不再被使用。

map_file //相容標誌,被忽略。

map_32bit //將對映區放在程序位址空間的低2gb,map_fixed指定時會被忽略。當前這個標誌只在x86-64平台上得到支援。

map_populate //為檔案對映通過預讀的方式準備好頁表。隨後對對映區的訪問不會被頁違例阻塞。

map_nonblock //僅和map_populate一起使用時才有意義。不執行預讀,只為已存在於記憶體中的頁面建立頁表入口。

fd:有效的檔案描述詞。一般是由open()函式返回,其值也可以設定為-1,此時需要指定flags引數中的map_anon,表明進行的是匿名對映。

offset:被對映物件內容的起點。

返回值說明

成功執行時,mmap()返回被對映區的指標,munmap()返回0。失敗時,mmap()返回map_failed[其值為(void *)-1],munmap返回-1。

errno被設為以下的某個值:

eacces:訪問出錯

eagain:檔案已被鎖定,或者太多的記憶體已被鎖定

ebadf:fd不是有效的檔案描述詞

einval:乙個或者多個引數無效

enfile:已達到系統對開啟檔案的限制

enodev:指定檔案所在的檔案系統不支援記憶體對映

enomem:記憶體不足,或者程序已超出最大記憶體對映數量

eperm:權能不足,操作不允許

etxtbsy:已寫的方式開啟檔案,同時指定map_denywrite標誌

sigse**:試著向唯讀區寫入

sigbus:試著訪問不屬於程序的記憶體區

記憶體對映寫檔案操作,可以分為如下步驟:

示例**

#include #include #include #include #include struct student

;int main(int argc, const char *ar**)

// 2.修改檔案大小

ret = ftruncate(fd, 3 * sizeof(struct student));

if(-1 == ret)

// 3.檔案對映

struct student *pstu = (struct student *)mmap(null,

3 * sizeof(struct student),

prot_write | prot_read, map_shared, fd, 0);

if(map_failed == (void *)pstu)

// 4.通過記憶體操作檔案

struct student *p = pstu;

p->id = 1; strcpy(p->name, "李四"); p->age = 18; p->score = 78.5; p++;

p->id = 2; strcpy(p->name, "張三"); p->age = 19; p->score = 88.5; p++;

p->id = 3; strcpy(p->name, "王五"); p->age = 21; p->score = 72.5;

// 5.關閉對映

munmap(pstu, 3 * sizeof(struct student));

// 6.關閉檔案

close(fd);

return 0;

}

記憶體對映讀檔案操作,可以分為如下步驟:

示例**

#include #include #include #include #include struct student

;int main(int argc, const char *ar**)

// 2.檔案對映

struct student *pstu = (struct student *)mmap(null,

3 * sizeof(struct student),

prot_read, map_shared, fd, 0);

if(map_failed == (void *)pstu)

// 3.通過記憶體操作檔案

struct student *p = pstu;

for(int i = 0; i < 3; i++)

// 4.關閉對映

munmap(pstu, 3 * sizeof(struct student));

// 5.關閉檔案

close(fd);

return 0;

}

記憶體對映檔案 虛擬記憶體

windows提供了3種進行記憶體管理的方法 虛擬記憶體,最適合用來管理大型物件或結構陣列。記憶體對映檔案,最適合用來管理大型資料流 通常來自檔案 以及在單個計算機上執行的多個程序之間共享資料。記憶體堆疊,最適合用來管理大量的小物件。再通俗點,就是比如 要讀取乙個檔案裡的東西 這時候你就得去硬碟讀,...

虛擬記憶體 mmap檔案記憶體對映

記憶體對映是虛擬記憶體系統的重要特性,即虛擬記憶體中的虛擬頁 virtual page 總是對應於磁碟上的物理頁 physical page 記憶體對映技術,可以使得使用檔案來初始化虛擬記憶體的內容 只在第一次引用到相應記憶體時,才會快取進主存 linux程序中可以使用mmap函式,建立乙個虛擬記憶...

對映虛擬記憶體

沒有任何額外維護資料的記憶體分配 mmap 分配 munmap 釋放 分配空間大小 4k length 4k 1 以頁為單位,每頁通常為4k 函式說明 void mmap void start,指定對映的虛擬位址 0由系統指定開始位置 size t length,對映空間大小 pagesize倍數 ...