简体   繁体   English

OSX / iOS上的虚拟内存与Windows的提交/保留行为

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

I'm a little bit confused in comparing the virtual memory system behaviour in OSX/iOS to that of Windows. 在比较OSX / iOS和Windows的虚拟内存系统行为时,我有些困惑。 The Windows VirtualAlloc() related functions and their behaviour regards reserving and the actual memory commit and de-commit are fairly straight forward. 与Windows VirtualAlloc()相关的功能及其在保留方面的行为以及实际的内存提交和取消提交都相当简单。

For OSX which is not well discussed I have been looking at mach_vm_allocate(), mach_vm_map() etc. For example if I wanted to create a set of cross platform functions to expose common virtual memory functionality between Windows and OSX/iOS how would I managed the difference between commit/de-commit on OSX as opposed to Windows? 对于未进行充分讨论的OSX,我一直在研究mach_vm_allocate(),mach_vm_map()等。例如,如果我想创建一组跨平台函数以公开Windows和OSX / iOS之间的通用虚拟内存功能,我将如何管理OSX与Windows上的提交/取消提交之间的区别?

As I am not sure I understand if you can reserve virtual address range and commit it as a separate action like on Windows? 我不确定我是否可以保留虚拟地址范围并将其作为单独的操作(例如在Windows上)提交? From my understanding mach_vm_allocate() is similar to VirtualAlloc() with MEM_COMMIT | 据我了解,mach_vm_allocate()与带有MEM_COMMIT的VirtualAlloc()类似。 MEM_RESERVE and also trying to compare which is actually a better designed mechanism if any is confusing. MEM_RESERVE并尝试比较哪一种实际上是一种更好设计的机制(如果有的话会引起混淆)。

Possibly I need better understanding of how the page managers function in OSX. 可能我需要更好地了解页面管理器在OSX中的功能。

On Windows even if you commit a region I suspect it may not actually back it with physical memory until you try accessing it unless perhaps there is currently abundant memory - and that it just guarantees swap file backing when modified. 在Windows上,即使您提交了一个区域,我也怀疑除非您尝试访问它,否则它实际上可能不会用物理内存备份它,除非当前可能有足够的内存-并且它只能保证修改后支持交换文件。

On OSX I am not sure how to de-commit regions but still keep the address range reserved? 在OSX上,我不确定如何取消提交区域,但是仍然保留地址范围吗? For example this sort of behaviour is useful in a 64bit programs (Which I am mostly interested in) to reserve a large virtual address range for an arena/stack/linear allocator with rewind ability - that requires being able to commit and de-commit the ends of regions. 例如,这种行为在64位程序(我最感兴趣的程序)中非常有用,可以为具有倒带功能的竞技场/堆栈/线性分配器保留较大的虚拟地址范围-这要求能够提交和取消提交地区的尽头。 In Windows it is obvious how to produce such behaviour but in OSX I don't quite understand how to efficiently replicate it. 在Windows中,很明显如何产生这种行为,但是在OSX中,我不太了解如何有效地复制它。

EDIT: 编辑:

I just found this: 我刚发现:

Reserve memory on OS X 在OS X上保留内存

That is relevant to my question but surely mmap() goes through the equivalent mach_vm_*() system calls? 这与我的问题有关, 但是 mmap()是否一定会通过等效的mach_vm _ *()系统调用?

EDIT2: EDIT2:

Typical I now find these: 现在,典型的我发现这些:

Does mmap with MAP_NORESERVE reserve physical memory? MAP_NORESERVE的mmap是否保留物理内存?

How can I reserve virtual memory in Linux? 如何在Linux中保留虚拟内存?

But it still perhaps doesn't clear up how to de-commit the way I would like too - but off to google some more on mmap() ANON stuff - and possibly see if I can find the mmap() source code for OSX (?). 但这也许仍未弄清如何取消提交我想要的方式-但在Google上进一步了解了mmap()ANON的内容-可能看看我是否可以找到OSX的mmap()源代码( ?)。

(For sure someone will say use mmap() as it works on linux too if I can figure out the de-commit issue but still I am curious how that gets routed through the mach_vm_*() calls...) (可以肯定的是,如果我能弄清取消提交的问题,肯定会说在Linux上也可以使用mmap(),但是我仍然很好奇如何通过mach_vm _ *()调用来路由它。)

EDIT3: EDIT3:

I found mremap() which together with mmap() looks useful! 我发现mremap()和mmap()看起来很有用! Obviously using PROT_NONE, MAP_NORESERVE with mmap() look interesting also. 显然,使用PROT_NONE和带有mmap()的MAP_NORESERVE看起来也很有趣。 But I am still unsure how you can de-commit regions but still keep the address range preserved as mremap() doesn't seem to be able to take MAP_NORESERVE to ditch the swap file backing? 但是我仍然不确定如何取消提交区域,但是仍然保留地址范围,因为mremap()似乎无法使用MAP_NORESERVE放弃交换文件的支持?

EDIT4: EDIT4:

I found this regards de-commits: https://bugzilla.mozilla.org/show_bug.cgi?id=670596 . 我发现此问题已取消提交: https : //bugzilla.mozilla.org/show_bug.cgi? id =670596 Which discusses the behaviour on OSX and Linux regards mprotect(addr, len, PROT_NONE) and madvise(). 其中讨论了mprotect(addr,len,PROT_NONE)和madvise()在OSX和Linux上的行为。 .. ..

EDIT5: (!) EDIT5:(!)

Digging through my Mac header files I find for madvise(): 浏览我发现的madvise()的Mac头文件:

#define MADV_WILLNEED POSIX_MADV_WILLNEED #定义MADV_WILLNEED POSIX_MADV_WILLNEED

#define MADV_DONTNEED POSIX_MADV_DONTNEED #define MADV_DONTNEED POSIX_MADV_DONTNEED

#define MADV_FREE 5 /* pages unneeded, discard contents */ #define MADV_FREE 5 / *不需要页面,丢弃内容* /

#define MADV_ZERO_WIRED_PAGES 6 /* zero the wired pages that have not been unwired before the entry is deleted */ #define MADV_ZERO_WIRED_PAGES 6 / *将删除条目之前尚未取消连线的有线页面清零* /

#define MADV_FREE_REUSABLE 7 /* pages can be reused (by anyone) */ #define MADV_FREE_REUSABLE 7 / *页面可以重复使用(任何人)* /

#define MADV_FREE_REUSE 8 /* caller wants to reuse those pages */ #define MADV_FREE_REUSE 8 / *呼叫者想重复使用这些页面* /

#define MADV_CAN_REUSE 9 #定义MADV_CAN_REUSE 9

So I am guessing MADV_FREE_REUSE should be preferred usage for de-commits? 因此,我猜测MADV_FREE_REUSE应该是取消提交的首选用法?

EDIT6: I have asked the question on the iOS/OSX developer forums and in the meantime I have come across these that may be helpful to other people wondering the same thing: EDIT6:我在iOS / OSX开发人员论坛上提出了这个问题,与此同时,我遇到了这些问题,可能对其他想知道同一件事的人有所帮助:

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

Also this: 还有这个:

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

Which seems like the key is mmap(), and madvise(), or mach_vm_allocate() and mach_vm_behavior_set() with flag VM_BEHAVIOR_DONTNEED. 似乎关键是带有标志VM_BEHAVIOR_DONTNEED的mmap()和madvise()或mach_vm_allocate()和mach_vm_behavior_set()。

Will report back for the benefit of others after experimenting with this... 经过尝试后,将回报他人的利益。

EDIT7: EDIT7:

Latest for now OSX 10.9 source code for mmap() and madvise() I think: http://www.opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_mman.c 我认为现在是最新的mmap()和madvise()的OSX 10.9源代码: http : //www.opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_mman.c

Seems to confirm mach_vm_behavior_set() 似乎要确认mach_vm_behavior_set()

EDIT8: EDIT8:

Ok now so far as I can tell from OSX 10.9: 现在,从OSX 10.9可以确定:

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

I should use mach_vm_allocate() and vm_map_behavior_set() with the (suggestive) flags being roughly equivalent in Windows VirtualAlloc() parlance too: 我也应该使用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(?)

But I am not sure what these mean exactly still(?): 但是我不确定这些到底是什么意思?

VM_BEHAVIOR_REUSABLE
VM_BEHAVIOR_REUSE
VM_BEHAVIOR_CAN_REUSE

I am hoping from confirmation from apple on the preferred usage pattern but I guess I am close to answering my own question with the above... 我希望得到苹果公司关于首选使用模式的确认,但我想我已经可以用上述方法回答自己的问题了...

This is the first time I have had the pleasure to dig through some very clean open source code :-) 这是我第一次有幸浏览一些非常干净的开源代码:-)

There's no exact analog. 没有确切的模拟。 In Unix-style OSes, allocated memory can be accessed and that will cause it to be associated with physical memory or swap. 在Unix风格的OS中,可以访问分配的内存,这将导致它与物理内存或交换关联。 But there's not always a guarantee that allocated memory has sufficient swap file space set aside for it. 但是,并不总是保证分配的内存具有足够的交换文件空间。 So, the system can fail to associate physical memory if it can't swap something else out to free up the RAM. 因此,如果无法交换其他东西来释放RAM,则系统可能无法关联物理内存。

Both vm_allocate() and mmap() reserve an address range. vm_allocate()mmap()保留一个地址范围。 They also both make it legal for the process to access the addresses in that range, at which point the pages will be mapped to physical memory if necessary. 它们还使该进程访问该范围内的地址合法,这时将在必要时将页面映射到物理内存。 However, on OS X, I don't believe that either function reserves backing storage (swap) for the address range. 但是,在OS X上,我认为这两个功能都不为该地址范围保留后备存储(交换)。

If you allocate some space and then access it, causing it to be mapped to RAM or swap, and you want to return it to just being allocated but clear the backing in RAM or swap, I believe that a second call to mmap() with MAP_FIXED will do that. 如果您分配了一些空间然后访问它,从而将其映射到RAM或交换,并且您想将其返回到刚刚分配的状态,但清除了RAM或交换中的支持,我相信对mmap()的第二次调用是MAP_FIXED将执行此操作。

I use method below on OS X and iOS: 我在OS X和iOS上使用以下方法:

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

// init and reserve memory //初始化并保留内存

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

// alloc memory size //分配内存大小

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

// dealloc and return to system memory size //取消分配并返回系统内存大小

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;

// deinit //取消初始化

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