4

正確にどのように機能するかを確認するためだけに、C で mmap を使用しようとしています。現在、mmap を使用してバイナリ ファイルをバイト単位で読み取ろうとしています。私のコードは次のようなものです:

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

int main(int argc, char *argv[]) {
    int fd;
    char *data;

    for ( int i = 1; i<argc; i++)
    {

        if(strcmp(argv[i],"-i")==0)
            fd = open(argv[i+1],O_RDONLY);
    }

    data = mmap(NULL, 4000, PROT_READ, MAP_SHARED, fd, 8000);
    int i = 0;
    notation = data [i];
    // ......

}

notation = data[0] を試して segfault を取得すると、問題が発生します。バイナリ ファイルの最初のバイトも文字であると確信しています。私の for ループは、コンパイル中に -i フラグがあるかどうかをチェックします。次の引数がある場合は、ファイル名にする必要があります。

4

1 に答える 1

4

オフセットがページ サイズの倍数ではないため、mmap が失敗したようです。これを perror でテストすると、問題が無効な引数であることがわかります。あなたが書く場合:

data = mmap(NULL, 4000, PROT_READ, MAP_SHARED, fd, 8000);
perror("Error");

少なくとも私の OS X では、次のエラーが表示されます。

エラー: 引数が無効です

オフセットを 8000 から 4096 または 8192 に変更すると機能します。6144 はそうではないので、このプラットフォームでは 4096 の倍数でなければなりません。ちなみに、

printf("%d\n",getpagesize());

4096 を出力します。領域にアクセスするときは、オフセットを mmap のこの倍数に最も近い値に切り捨て、残りを i に追加する必要があります。もちろん、その関数から特定のプラットフォームのページ サイズを取得します。おそらく、すでに宣言したunistd.hで定義されています。

オフセットを正しく処理し、起こりうるエラーに対処する方法は次のとおりです。位置 8000 のバイトを出力します。

int offset = 8000;
int pageoffset = offset % getpagesize();

data = mmap(NULL, 4000 + pageoffset, PROT_READ, MAP_SHARED, fd, offset - pageoffset);
if ( data == MAP_FAILED ) {
    perror ( "mmap" );
    exit ( EXIT_FAILURE );
}
i = 0;
printf("%c\n",data [i + pageoffset]);
于 2012-04-15T17:40:07.823 に答える