簡體   English   中英

映射的文件在讀取時不會占用內存,但在寫入時會占用內存

[英]Mapped file doesn't take memory on read, but does on write

我觀察到一種怪異的行為,其中一個大內存映射文件(2GB)在我從中讀取時並沒有占用實際的物理RAM,但是當我開始對其進行寫入時卻會占用。

int err = 0;

int fd = open("large_file", O_RDWR);
if (fd == -1) {
    return errno;
}

void *map = mmap(NULL, size, PROT_READ | PROT_WRITE, 
                 MAP_PRIVATE, fd, 0); 
if (map == MAP_FAILED) {
     err = errno;
     goto out;
}

for (unsigned int i = 0; i < 2 << 30; i += PAGE_SIZE) {
      volatile uint8_t val = 0xff;

      // val = ((volatile uint8_t *) map)[i]; /* Doesn't take actual memory */
      // ((volatile uint8_t *) map[i]) = val; /* Takes actual memory */
}

while (1)
    sleep(10);

out:
   if (fd != -1)
      close(fd);
   if (map != MAP_FAILED)
      munmap(map, size);
return err;

這是我從映射文件讀取時的htop屏幕截圖(查看“檢查”)

這是我寫入映射文件時的htop屏幕截圖(查看“檢查”

我的筆記本電腦幾乎是閑置的,除了測試過程外沒有其他東西可以占用物理內存,因此您可以看到當我寫入映射文件時實際上需要2GB(寫時復制),而在讀取時卻不需要。 RES-SHR也適合我的兩種情況。

我無法解釋..內核映射新頁面,無論它是對物理RAM的讀取還是寫入。 如果不存在,則應將其映射,並在出現頁面錯誤異常后獲取實際的RAM。 映射的文件映射到其他進程,因此不共享。 測試過程是將文件映射到內存的唯一過程,也是第一個過程。

編輯:我添加了(volatile)關鍵字,以確保編譯器不會優化關鍵代碼。 這沒有任何區別。 這段特定的匯編代碼是從內存映射文件讀取的輸出:

mov    BYTE PTR [rbp-0xbd],0xff /* volatile uint8_t val = 0xff; */
mov    edx,DWORD PTR [rbp-0xbc] 
mov    rax,QWORD PTR [rbp-0xb0]
add    rax,rdx
movzx  eax,BYTE PTR [rax]     
mov    BYTE PTR [rbp-0xbd],al   /* val = ((volatile uint8_t *)map)[i]; */
add    DWORD PTR [rbp-0xbc],0x1000 /* i += PAGE_SIZE; */

有什么想法嗎?

可能您的編譯器只是優化了讀取訪問。 可以做到這一點,因為您永遠不會做任何事情。 最簡單的是更改val的聲明:

uint8_t volatile val = ... ;

但您也可以相應地聲明map

uint8_t volatile*map = mmap(NULL, size, PROT_READ | PROT_WRITE, 
             MAP_PRIVATE, fd, 0);

(聲明map類型也可以避免稍后再進行討厭的轉換。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM