簡體   English   中英

OSX / iOS上的虛擬內存與Windows的提交/保留行為

[英]Virtual Memory on OSX/iOS versus Windows commit/reserve behaviour

在比較OSX / iOS和Windows的虛擬內存系統行為時,我有些困惑。 與Windows VirtualAlloc()相關的功能及其在保留方面的行為以及實際的內存提交和取消提交都相當簡單。

對於未進行充分討論的OSX,我一直在研究mach_vm_allocate(),mach_vm_map()等。例如,如果我想創建一組跨平台函數以公開Windows和OSX / iOS之間的通用虛擬內存功能,我將如何管理OSX與Windows上的提交/取消提交之間的區別?

我不確定我是否可以保留虛擬地址范圍並將其作為單獨的操作(例如在Windows上)提交? 據我了解,mach_vm_allocate()與帶有MEM_COMMIT的VirtualAlloc()類似。 MEM_RESERVE並嘗試比較哪一種實際上是一種更好設計的機制(如果有的話會引起混淆)。

可能我需要更好地了解頁面管理器在OSX中的功能。

在Windows上,即使您提交了一個區域,我也懷疑除非您嘗試訪問它,否則它實際上可能不會用物理內存備份它,除非當前可能有足夠的內存-並且它只能保證修改后支持交換文件。

在OSX上,我不確定如何取消提交區域,但是仍然保留地址范圍嗎? 例如,這種行為在64位程序(我最感興趣的程序)中非常有用,可以為具有倒帶功能的競技場/堆棧/線性分配器保留較大的虛擬地址范圍-這要求能夠提交和取消提交地區的盡頭。 在Windows中,很明顯如何產生這種行為,但是在OSX中,我不太了解如何有效地復制它。

編輯:

我剛發現:

在OS X上保留內存

這與我的問題有關, 但是 mmap()是否一定會通過等效的mach_vm _ *()系統調用?

EDIT2:

現在,典型的我發現這些:

MAP_NORESERVE的mmap是否保留物理內存?

如何在Linux中保留虛擬內存?

但這也許仍未弄清如何取消提交我想要的方式-但在Google上進一步了解了mmap()ANON的內容-可能看看我是否可以找到OSX的mmap()源代碼( ?)。

(可以肯定的是,如果我能弄清取消提交的問題,肯定會說在Linux上也可以使用mmap(),但是我仍然很好奇如何通過mach_vm _ *()調用來路由它。)

EDIT3:

我發現mremap()和mmap()看起來很有用! 顯然,使用PROT_NONE和帶有mmap()的MAP_NORESERVE看起來也很有趣。 但是我仍然不確定如何取消提交區域,但是仍然保留地址范圍,因為mremap()似乎無法使用MAP_NORESERVE放棄交換文件的支持?

EDIT4:

我發現此問題已取消提交: https : //bugzilla.mozilla.org/show_bug.cgi? id =670596 其中討論了mprotect(addr,len,PROT_NONE)和madvise()在OSX和Linux上的行為。 ..

EDIT5:(!)

瀏覽我發現的madvise()的Mac頭文件:

#定義MADV_WILLNEED POSIX_MADV_WILLNEED

#define MADV_DONTNEED POSIX_MADV_DONTNEED

#define MADV_FREE 5 / *不需要頁面,丟棄內容* /

#define MADV_ZERO_WIRED_PAGES 6 / *將刪除條目之前尚未取消連線的有線頁面清零* /

#define MADV_FREE_REUSABLE 7 / *頁面可以重復使用(任何人)* /

#define MADV_FREE_REUSE 8 / *呼叫者想重復使用這些頁面* /

#定義MADV_CAN_REUSE 9

因此,我猜測MADV_FREE_REUSE應該是取消提交的首選用法?

EDIT6:我在iOS / OSX開發人員論壇上提出了這個問題,與此同時,我遇到了這些問題,可能對其他想知道同一件事的人有所幫助:

http://lists.apple.com/archives/PerfOptimization-dev/2009/Apr/msg00024.html http://markmail.org/message/yqwqd3zuawz6v5dd

還有這個:

http://fxr.watson.org/fxr/source/bsd/kern/kern_mman.c?v=xnu-1228;im=bigexcerpts#L824

似乎關鍵是帶有標志VM_BEHAVIOR_DONTNEED的mmap()和madvise()或mach_vm_allocate()和mach_vm_behavior_set()。

經過嘗試后,將回報他人的利益。

EDIT7:

我認為現在是最新的mmap()和madvise()的OSX 10.9源代碼: http : //www.opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_mman.c

似乎要確認mach_vm_behavior_set()

EDIT8:

現在,從OSX 10.9可以確定:

http://www.opensource.apple.com/source/xnu/xnu-2422.1.72/osfmk/vm/vm_map.c

我也應該使用mach_vm_allocate()和vm_map_behavior_set(),並且(建議)標志在Windows VirtualAlloc()中也大致等效:

VM_BEHAVIOR_WILLNEED => Commit address range
VM_BEHAVIOR_DONTNEED => Decommit address range
VM_BEHAVIOR_FREE => Decommit and completely release address range(?)

但是我不確定這些到底是什么意思?

VM_BEHAVIOR_REUSABLE
VM_BEHAVIOR_REUSE
VM_BEHAVIOR_CAN_REUSE

我希望得到蘋果公司關於首選使用模式的確認,但我想我已經可以用上述方法回答自己的問題了...

這是我第一次有幸瀏覽一些非常干凈的開源代碼:-)

沒有確切的模擬。 在Unix風格的OS中,可以訪問分配的內存,這將導致它與物理內存或交換關聯。 但是,並不總是保證分配的內存具有足夠的交換文件空間。 因此,如果無法交換其他東西來釋放RAM,則系統可能無法關聯物理內存。

vm_allocate()mmap()保留一個地址范圍。 它們還使該進程訪問該范圍內的地址合法,這時將在必要時將頁面映射到物理內存。 但是,在OS X上,我認為這兩個功能都不為該地址范圍保留后備存儲(交換)。

如果您分配了一些空間然后訪問它,從而將其映射到RAM或交換,並且您想將其返回到剛剛分配的狀態,但清除了RAM或交換中的支持,我相信對mmap()的第二次調用是MAP_FIXED將執行此操作。

我在OS X和iOS上使用以下方法:

char* m_base = 0;
unsigned m_offset = 0;
unsigned MAX_SIZE = 1024 * 1024 * 10; // 10 Mb

//初始化並保留內存

kern_return_t err = vm_allocate(mach_task_self(), (vm_address_t*)&m_base, MAX_SIZE, VM_FLAGS_ANYWHERE);

//分配內存大小

size = (size + roundToPageSize - 1) & ~(roundToPageSize - 1);
char* address = m_base + m_offset;
kern_return_t err = vm_allocate(mach_task_self(), (vm_address_t*)&address, size, VM_FLAGS_FIXED|VM_FLAGS_OVERWRITE);
m_offset += size;
// now address points to allocated memory in reserved space

//取消分配並返回系統內存大小

size = (size + roundTo - 1) & ~(roundTo - 1);
char* address = m_base + m_offset - size;
kern_return_t err = vm_deallocate(mach_task_self(), (vm_address_t)address, size);
m_offset -= size;

//取消初始化

kern_return_t err = vm_deallocate(mach_task_self(), (vm_address_t)m_base, MAX_SIZE);
m_base = 0;
m_offset = 0;

暫無
暫無

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

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