4

これは、2.6.26-2-amd64 Linuxカーネルで、コピーオンライトセマンティクス(PROT_READ | PROT_WRITEおよびMAP_PRIVATE)を使用して5GBファイルをmmapしようとしたときに発生します。4GB未満のファイルのマッピング、またはPROT_READのみを使用したファイルは正常に機能します。この質問で報告されているように、これはソフトリソース制限の問題ではありません。仮想制限サイズは無制限です。

これが問題を再現するコードです(実際のコードはBoost.Interprocessの一部です)。

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <fcntl.h>
#include <unistd.h>

main()
{
        struct stat b;
        void *base;
        int fd = open("foo.bin", O_RDWR);

        fstat(fd, &b);
        base = mmap(0, b.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
        if (base == MAP_FAILED) {
                perror("mmap");
                return 1;
        }
        return 0;
}

そしてここに何が起こるかです:

dd if=/dev/zero of=foo.bin bs=1M seek=5000 count=1
./test-mmap
mmap: Cannot allocate memory

これは、nosによって尋ねられた、関連するstrace(新しくコンパイルされた4.5.20)の出力です。

open("foo.bin", O_RDWR)                 = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=5243928576, ...}) = 0
mmap(NULL, 5243928576, PROT_READ|PROT_WRITE, MAP_PRIVATE, 3, 0) = -1 ENOMEM (Cannot allocate memory)
dup(2)                                  = 4
[...]
write(4, "mmap: Cannot allocate memory\n", 29mmap: Cannot allocate memory
) = 29
4

2 に答える 2

5

MAP_NORESERVE次のようにflagsフィールドを渡してみてください。

mmap(NULL, b.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_NORESERVE, fd, 0);

スワップと物理メモリの組み合わせが、要求された5GB未満である可能性があります。

または、テスト目的でこれを行うこともできます。機能する場合は、上記のコードを変更できます。

# echo 0 > /proc/sys/vm/overcommit_memory

以下は、マニュアルページからの関連する抜粋です。

mmap(2):

   MAP_NORESERVE
          Do  not reserve swap space for this mapping.  When swap space is
          reserved, one has the guarantee that it is  possible  to  modify
          the  mapping.   When  swap  space  is not reserved one might get
          SIGSEGV upon a write if no physical memory  is  available.   See
          also  the  discussion of the file /proc/sys/vm/overcommit_memory
          in proc(5).  In kernels before 2.6, this flag  only  had  effect
          for private writable mappings.

proc(5):

   /proc/sys/vm/overcommit_memory
          This file contains the kernel virtual  memory  accounting  mode.
          Values are:

                 0: heuristic overcommit (this is the default)
                 1: always overcommit, never check
                 2: always check, never overcommit

          In  mode 0, calls of mmap(2) with MAP_NORESERVE are not checked,
          and the default check is very weak, leading to the risk of  get‐
          ting a process "OOM-killed".  Under Linux 2.4 any non-zero value
          implies mode 1.  In mode 2  (available  since  Linux  2.6),  the
          total  virtual  address  space on the system is limited to (SS +
          RAM*(r/100)), where SS is the size of the swap space, and RAM is
          the  size  of  the physical memory, and r is the contents of the
          file /proc/sys/vm/overcommit_ratio.
于 2010-09-01T03:53:28.780 に答える
2

コメントからメモリ、スワップサイズ、オーバーコミット設定を引用します。

MemTotal: 4063428 kB SwapTotal: 514072 kB
$ cat /proc/sys/vm/overcommit_memory
0
$ cat /proc/sys/vm/overcommit_ratio 
50

0(「ヒューリスティックオーバーコミット」)にovercommit_memory設定すると、現在の空きメモリとスワップの合計よりも大きいプライベートで書き込み可能なマッピングを作成できません。明らかに、4.5GBのメモリとスワップしかないため、これは決して真実ではありません。 。

空きメモリとスワップがあるよりも多くのページをマッピングでダーティ(書き込み)しないことが確実な場合は、MAP_NORESERVEMatt Joinerが提案するように)使用するオプションがあります。または、スワップスペースのサイズを大幅に増やします。

于 2010-09-01T06:00:07.793 に答える