簡體   English   中英

是否可以在linux中分配大量虛擬memory?

[英]Is it possible to allocate large amount of virtual memory in linux?

對於某些目的而言,分配大量虛擬空間並僅在訪問的頁面中分頁會很有效。 分配大量的 memory 是瞬時的,實際上並不搶頁:

char* p = new char[1024*1024*1024*256];

好的,上面指出的是錯誤的,因為它是一個 32 位數字。

我希望 new 正在調用調用 sbrk 的 malloc,並且當我訪問開始后 4Gb 的位置時,它會嘗試將任務 memory 擴展那么多?

這是完整的程序:

#include <cstdint>
int main() {
  constexpr uint64_t GB = 1ULL << 30;
  char* p = new char[256*GB]; // allocate large block of virtual space
  p[0] = 1;
  p[1000000000] = 1;
  p[2000000000] = 1;
}

現在,我在嘗試分配大量金額時得到了 bad_alloc,所以顯然 malloc 不起作用。

我的印象是 mmap 會將 map 寫入文件,但由於有人建議我正在研究它。

好的,所以 mmap 似乎支持分配虛擬 memory 的大區域,但它需要一個文件描述符。 創建巨大的內存數據結構可能是一個勝利,但如果它們必須由文件支持,則不是:

即使我不喜歡附加到文件的想法,以下代碼也使用 mmap。 我不知道在虛擬 memory 中請求輸入什么號碼,然后選擇了 0x800000000。 mmap 返回-1,所以很明顯我做錯了什么:

#include <cstdint>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

int main() {
  constexpr uint64_t GB = 1ULL << 30;
  void *addr = (void*)0x8000000000ULL;
  int fd = creat("garbagefile.dat", 0660);
  char* p = (char*)mmap(addr, 256*GB, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
  p[0] = 1;
  p[1000000000] = 1;
  p[2000000000] = 1;
  close(fd);
}

有沒有辦法分配一大塊虛擬 memory 並稀疏地訪問頁面,或者這不可行?

256*GB的值不適合 32 位 integer 類型的范圍。 嘗試uint64_t作為一種GB

constexpr uint64_t GB = 1024*1024*1024;

或者,強制 64 位乘法:

char* p = new char[256ULL * GB];

OT:我更喜歡GB的這個定義:

constexpr uint64_t GB = 1ULL << 30;

至於虛擬 memory 限制,看這個答案

是否可以在linux中分配大量虛擬memory?

可能。 但是您可能需要將其配置為允許:

Linux kernel 支持以下過載處理模式

0 - 啟發式過度使用處理。 明顯的地址空間過度使用被拒絕。 用於典型系統。 它確保嚴重的瘋狂分配失敗,同時允許過度使用以減少交換使用。 在這種模式下,root 可以分配稍微多一點的 memory。 這是默認設置。

1 - 總是過度使用。 適用於一些科學應用。 經典示例是使用稀疏 arrays 並僅依賴幾乎完全由零頁組成的虛擬 memory 的代碼。

2 - 不要過度使用。 系統的總地址空間提交不允許超過交換 + 物理 RAM 的可配置數量(默認為 50%)。 根據您使用的數量,在大多數情況下,這意味着進程在訪問頁面時不會被終止,但會在 memory 分配上收到錯誤。

對於希望保證其 memory 分配將來可用而無需初始化每個頁面的應用程序很有用。

過量使用策略是通過 sysctl `vm.overcommit_memory' 設置的。

因此,如果您想分配比物理 memory 更多的虛擬 memory,那么您需要:

# in shell
sysctl -w vm.overcommit_memory=1

RLIMIT_AS 進程的虛擬 memory(地址空間)的最大大小,以字節為單位。 此限制會影響對 brk(2)、mmap(2) 和 mremap(2) 的調用,超過此限制時會失敗並返回錯誤 ENOMEM。 自動堆棧擴展也會失敗(如果沒有通過 sigaltstack(2) 提供備用堆棧,則會生成一個終止進程的 SIGSEGV)。 由於該值為 long,因此在具有 32 位長度的機器上,此限制最多為 2 GiB,或者此資源是無限的。

所以,你會想要:

setrlimit(RLIMIT_AS, {
    .rlim_cur = RLIM_INFINITY,
    .rlim_max = RLIM_INFINITY,
});

或者,如果您不能授予進程執行此操作的權限,那么您可以在 /etc/security/limits.conf 中持久配置它,這將影響(用戶/組的)所有進程。


好的,所以 mmap 似乎支持......但它需要一個文件描述符。 ...可能是勝利,但如果他們必須得到文件的支持,則不會...我不喜歡附加到文件的想法

您不需要使用文件支持的 mmap。 有 MAP_ANONYMOUS 。

我不知道輸入什么號碼來請求

然后使用 null。 例子:

mmap(nullptr, 256*GB, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)

也就是說,如果您按照描述配置了系統,那么new應該和mmap一樣工作。 它可能會使用malloc ,這可能會使用mmap進行像這樣的大分配。


額外提示:您可能會受益於使用HugeTLB Pages

暫無
暫無

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

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