web-dev-qa-db-ja.com

読み書きmmapの引数が無効ですか?

-EINVAL何らかの理由で、なぜなのかはっきりしていません。ここで、ファイルを開いてmmapを試みます。

if ((fd = open(argv[1], O_RDWR)) < 0)
{
    fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));
    return 1;
}

struct stat statbuf;
if (fstat(fd, &statbuf))
{
    fprintf(stderr, "stat filed: %s\n", strerror(errno));
    return 1;
}

char* fbase = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (fbase == MAP_FAILED)
{
    fprintf(stderr, "mmap failed: %s\n", strerror(errno));
    return 1;
}

編集:追加する必要があります、エラーはmmapで発生しています。

20
Alex

MAP_SHAREDMAP_PRIVATEに変更すると、これを成功させることができます。

これが失敗したこの理由は微妙です。私のコードはVirtualBox VM内で実行されており、mmapにしようとしていたファイルはホストマシンの共有ディレクトリにありました。 VirtualBox仮想ファイルシステムは、ハイパーバイザーの境界を越えてMAP_SHAREDオプションを指定したmmapを実装していないようです。

私の質問と彼の回答の両方についてjxhの役立つコメントを読むと、彼がホストのファイルシステムファイルをホストメモリにmmapしようとしたため、このコードがうまく機能していることがわかります。

MAP_SHAREDからMAP_PRIVATEへの切り替えもこれと一致しています。プライベートにマップされたメモリは他のプロセスから見えないため、仮想ファイルシステムドライバーはおそらくメモリのマッピングに異論はありません。

解決策は、マップしたいファイルをゲストのハードドライブに移動し、そこから操作を実行することでした。

55
Alex

あなたの_statbuf.st_size_は_0_です。 mmap()lengthパラメータが_0_の場合、失敗します。

EINVALエラーmmap()には3つの理由がリストされています:

_void *mmap(void *addr, size_t length, int prot, int flags,
           int fd, off_t offset);
_

...

  • addrlength、またはoffsetは好きではありません(たとえば、サイズが大きすぎるか、ページ境界に配置されていません)。
  • (Linux 2.6.12以降)lengthは0でした。
  • flagsに_MAP_PRIVATE_も_MAP_SHARED_も含まれていないか、これらの値の両方が含まれています。
15
jxh