繁体   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