我正在尝试使用 mmap 在 iOS 上读取和播放音频文件。它适用于最大约 400MB 的文件。但当我尝试 500MB 文件时,出现 ENOMEM 错误。
char *path = [[[NSBundle mainBundle] pathForResource: @"test500MB" ofType: @"wav"] cStringUsingEncoding: [NSString defaultCStringEncoding]];
FILE *f = fopen( path, "rb" );
fseek( f, 0, SEEK_END );
int len = (int)ftell( f );
fseek( f, 0, SEEK_SET );
void *raw = mmap( 0, len, PROT_READ, MAP_SHARED, fileno( f ), 0 );
if ( raw == MAP_FAILED ) {
printf( "MAP_FAILED. errno=%d", errno ); // Here it says 12, which is ENOMEM.
}
Why?
我很高兴得到这样的答案:“700MB 是虚拟内存限制,但有时地址空间是碎片化的,所以你确实会得到 700MB,但分成较小的块”。 (这只是猜测,我还需要答案)
关于虚拟内存的苹果文档页面说:
尽管 OS X 支持后备存储,但 iOS 不支持。在iPhone中
应用程序、磁盘上已有的只读数据(例如代码
页)只是从内存中删除并根据需要从磁盘重新加载。
这似乎证实 mmap 应该适用于大于物理内存的块,但仍然无法解释为什么我达到如此低的限制。
Update
-
这个答案 https://stackoverflow.com/questions/9184773/is-there-a-practical-limit-on-the-number-of-memory-mapped-files-in-ios很有趣,但 500MB 远低于它提到的 700MB 限制。
-
这次讨论 https://stackoverflow.com/questions/726471/how-big-can-a-memory-mapped-file-be?rq=1提及连续内存。那么内存碎片可能是一个真正的问题吗?
- 我使用的是第四代 iPod Touch,它有 256MB 物理内存。
- 我研究的目的是看看在从文件加载只读数据时是否有更好的内存管理方法“继续分配,直到收到内存警告”.
mmap
似乎是解决这个问题的好方法......
Update 2
我希望 mmap 能够与新的 64 位版本的 iOS 完美配合。一旦我拿到 64 位设备就会进行测试。