iOSでmmapを使用してオーディオファイルを読み取って再生しようとしています。約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.
}
なんで?
「700MBは仮想メモリの制限ですが、アドレススペースが断片化されていることがあるため、700MBを取得しますが、チャンクは小さくなります」などの回答に満足しています。(これは単なる推測です、私はまだ答えが必要です)
仮想メモリに関するAppleのドキュメントページには次のように書かれています。
OS Xはバッキングストアをサポートしていますが、iOSはサポートしていません。iPhoneアプリケーションでは、すでにディスク上にある読み取り専用データ(コードページなど)は、メモリから削除され、必要に応じてディスクから再ロードされます。
これは、mmapが物理メモリよりも大きいブロックで機能することを確認しているようですが、それでも、なぜこのような下限に達しているのかを説明していません。
アップデート
- この答えは興味深いものですが、500MBはそれが言及している700MBの制限をはるかに下回っています。
- このディスカッションでは、連続したメモリについて説明します。では、メモリの断片化が実際の問題になる可能性がありますか?
- 256MBの物理メモリを搭載したiPodTouch第4世代を使用しています。
- 私の研究のポイントは、 「メモリ警告が表示されるまで割り当てを続ける」よりも、ファイルから読み取り専用データをロードするときにメモリを管理するためのより良い方法があるかどうかを確認することです。
mmap
これを解決する良い方法のように思えました...
アップデート2
mmapは新しい64ビットバージョンのiOSで完全に機能することを期待しています。64ビットデバイスを手に入れたらテストします。