9

私はopenSUSE11.2x86_64で大きなスパースファイルを扱ってきました。1TBのスパースファイルをmmap()しようとすると、ENOMEMで失敗します。テラバイト単位でマップするには64ビットのアドレス空間で十分だと思いましたが、そうではないようです。さらに実験すると、1GBのファイルは正常に機能しますが、2GBのファイル(およびそれより大きいファイル)は失敗します。どこかに微調整する設定があるのではないかと思いますが、大規模な検索では何も見つかりません。

問題を示すサンプルコードを次に示します-手がかりはありますか?

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    char * filename = argv[1];
    int fd;
    off_t size = 1UL << 40; // 30 == 1GB, 40 == 1TB

    fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
    ftruncate(fd, size);
    printf("Created %ld byte sparse file\n", size);

    char * buffer = (char *)mmap(NULL, (size_t)size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if ( buffer == MAP_FAILED ) {
        perror("mmap");
        exit(1);
    }
    printf("Done mmap - returned 0x0%lx\n", (unsigned long)buffer);

    strcpy( buffer, "cafebabe" );
    printf("Wrote to start\n");

    strcpy( buffer + (size - 9), "deadbeef" );
    printf("Wrote to end\n");

    if ( munmap(buffer, (size_t)size) < 0 ) {
        perror("munmap");
        exit(1);
    }
    close(fd);

    return 0;
}
4

3 に答える 3

14

問題は、プロセスごとの仮想メモリの制限がわずか1.7GBに設定されていたことです。ulimit -v 16106127361.5TBに設定すると、mmap()の呼び出しが成功しました。ulimit -aを試すためのヒントをありがとう、bmargulies !

于 2010-05-27T05:49:57.437 に答える
2

ユーザープロセスで使用できるメモリの量を制限する、ある種のユーザーごとの割り当てはありますか?

于 2010-05-26T03:42:32.487 に答える
1

私の推測では、カーネルはこのメモリマッピングに対応するために必要なメモリを割り当てるのに苦労しています。Linuxカーネルでスワップアウトされたページがどのように維持されているかはわかりませんが(ほとんどの場合、ファイルのほとんどがスワップアウトされた状態になると思います)、ページごとにエントリが必要になる可能性がありますファイルがテーブルで占めるメモリの量。このファイルは複数のプロセスによってmmapされる可能性があるため、カーネルはプロセスの観点からのマッピングに対応する必要があります。これにより、別の観点にマッピングされ、セカンダリストレージにマッピングされます(デバイスと場所のフィールドが含まれます)。 )。

これはアドレス指定可能なスペースに収まりますが、物理メモリ内に(少なくとも連続して)収まらない場合があります。

Linuxがこれをどのように行うかについてもっと知っている人がいたら、私はそれについて聞きたいと思います。

于 2010-05-26T04:35:34.670 に答える