2012-02-03 23 views
6

私はmmap()を使って仮想メモリを操作しようとしています。私はメモリの領域を予約してコミットしたい。私はこのコードをテストした:大きなサイズの呼び出しのmmap()が失敗しないのはなぜですか?

const unsigned long gygabyte = 1024 * 1024 * 1024; 
const unsigned long gygabyteCount = 2; 
const unsigned long maxCapacity = gygabyteCount * gygabyte; 

int main() 
{ 
    char* pMemory; 

    pMemory = (char*)mmap(NULL, maxCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
    if (mprotect(pMemory, maxCapacity, PROT_READ | PROT_WRITE) != 0) 
    { 
     cout << "Memory Allocation has failed" << endl; 
    } 
    usleep(-1); 

    return 0; 
} 

端末からいくつかの私のプログラム(例えば6)を走らせた。私は "Memory Allocation has failed"を見たことはありませんでした。私は4GBのRAMを搭載した64ビットのUbuntuで動作しています。誰も私にこれについて何か教えてもらえますか?

+1

メモリオーバーコミットについて読む – PlasmaHH

+0

投稿したコードは何もコミットしません。それらのメモリ領域を歩き回ってみてください。 – Mat

答えて

11

mmapは、領域を確保し:地域全体のためにこれらのフラグを渡すとmmapを呼び出した時点で行うことができますので、あなたは、mprotectに別のコールを必要としない、あなたの特定のケースで

プロセスの仮想アドレス空間を使用しますが、すぐに物理RAMを割り当てません。したがって、64ビットプラットフォームでは、膨大な量を失敗なしに予約できます(ただし、まだ失敗していないかどうかを確認する必要がありますが、サンプルコードでは確認していません)。 RAMの物理ページは、メモリにアクセスすると後で割り当てられます。

mprotectは予約メモリの読み書きアクセスを変更するだけです。 RAMに常駐させることはありません。 PROT_NONEの代わりにPROT_READ | PROT_WRITEmmapに渡し、mprotectへの呼び出しを削除することで同じ効果が得られます。

メモリをRAMに常駐させる必要がある場合は、mlockを使用してください。十分なRAMがない場合は失敗します。多くのLinuxプラットフォーム(Ubuntuを含む)では、プロセスがロックできるメモリ量を制限するリソース制限(RLIMIT_MEMLOCK)があります。これをulimit -lで調整できます。

+0

このようにする必要がありますか? 'pMemory =(char *)mmap(NULL、maxCapacity、PROT_READ | PROT_WRITE、MAP_SHARED | MAP_ANONYMOUS、-1、0); mlock(pMemory、maxCapacity) 'mlock()で使われているメモリはmmap()によって予約されているメモリではないと思います。 – antpetr89

+0

私は1GBを予約しようとしました。しかし、mlock()は-1を返しました。 – antpetr89

+1

@ user1173593:その後、 'errno'の値を確認してください。あなたのリソースの制限が低すぎる( 'ulimit -l'で設定できますが、おそらくはハード制限があるかもしれません)、またはおそらく' ENOMEM'で十分なメモリがないことを示す 'EPERM'かもしれません、またはマンページに記載されているその他のエラー。 –

0

まず、mmapの結果を確認する必要があります。 MAP_FAILEDを返す場合は、割り当てが失敗したことを意味します。カーネルは実際には一度に多くのメモリを割り当てませんが、そのブロックの対応する領域にアクセスするときに、オンデマンドで物理またはスワップ領域をマップします。

pMemory = mmap(NULL, maxCapacity, 
    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 

if (pMemory == MAP_FAILED) { 
    /* allocation failed */ 
} 
1

mmapは、要求するメモリのマッピングを準備するのに便利ですが、プログラムに割り当てません。あなたがそれらに同時にアクセスしないと、カーネルはあなたがそれにアクセスするときにメモリを割り当てます。したがって、mmap - 4GBメモリで8GBが可能です。

0

まず、あなたはそれが会計コミットやりたいのLinuxを伝える必要があります:

echo "2" > /proc/sys/vm/overcommit_memory 

をそれ以外の場合は、無制限のオーバーコミットを許可し、恐ろしくアプリを作る(LinuxはおもちゃのOSだったときから)レガシーのデフォルトを保持します物理メモリが不足したときにクラッシュします。

また、他の人も述べたように、mmapの戻り値をMAP_FAILEDに対して確認する必要があります。mprotectを使用する必要はありません。まず、PROT_*という正しい値をmmapに渡します。

関連する問題