0

メモリ内に大量のデータを生成するCプログラムがあり、このデータの特定のセクションをメモリ内で共有して、別のプロセスがそのセクションに読み取りアクセスできるようにする必要があります。

私はmmapこれを行うために使用しようとしていますが、あまり成功していません。これが私のコードです:

//Code above generates a pointer to the memory section I need to share, named addr

if (infoBlock->memory_size == 1073741824) { //This is the data block I need to share
   int err, fd;
   fd = open("/tmp/testOutput", (0_RDWR | 0_CREAT), S_IWUSR);
   if (fd < 0) {
         perror("Couldn't create output file\n");
         goto failedExit;
    }

    unsigned *p = mmap(addr, 1073741824, PROT_READ, (MAP_SHARED | MAP_FIXED), fd, 0);
    if (!p) {perror("mmap failed"); goto failedExit; }
    printf("p is now: %p\n", p); //This should point to the shared mapping
    printf("%u\n", *p); //Try to print out some data from the mapping

}

プログラムを実行した後、ファイル/ tmp / testOutputがそこにあることがわかりますが、サイズは0です。技術的にはファイルではないため、これがメモリマッピングで正常なものかどうかはわかりません。また、私のプログラム内のすべての出力は同じメモリアドレスを指しています。

/ tmp / testOutputを参照して、/ proc / PID/maps内に存在するメモリマップも確認できます。

すべてが実行されているように見えますが、ポインターの逆参照に関しては、プログラムが終了します。これは、マッピングを間違って行ったためであり、ポインターが本来あるべきではないものを指しているためだと思います。

誰かが私が間違っていることを見つけたり、アドバイスを提供したりすることができれば、それは大いにありがたいです。

ありがとう!

4

2 に答える 2

5

そのファイルに関連付けられている(または試みた)ストレージをプロセスにマップし、他の目的ですでに使用している(おそらくaddr何らかの方法で割り当てられた)アドレスにマップすることを主張しました。

あなたは実際にあなたが要求したアドレスを持っているかどうかを言いませんp、そして容疑者が指摘するように、あなたのエラーチェックは壊れています。

あなたの混乱:

事後に、任意のヒープまたは他のプロセスメモリページをファイルに関連付けることはできません。それらをファイルシステムに割り当ててから、マップする必要があります。(vmspliceを使用してそれらをUNIXパイプに関連付ける方法がありますが、それはあなたが要求したものとは正確には異なります)。

MMAP_FIXEDフラグは、データによって占有されていたページを、ファイルに関連付けられた新しいページに置き換えるだけであることに注意してください。そのフラグがないと、アドレスヒントは無視され、マッピングは別の場所に配置されます。

ソリューション:

  1. マッピングする前に、ファイルを目的のサイズに切り捨てます(これにより、ファイルシステムにストレージが割り当てられます)
  2. マップしてからデータ入力します
  3. mmapエラーチェックを修正する

割り当てスキームを変更できない場合、管理できる最善の方法は、プロセスローカルメモリをマッピングにコピーwriteすることです。この場合は、ファイルにコピーすることもできます。

理想的なケースは次のようになります。

void *alloc_mmap(const char *filename, size_t length)
{
    int fd;
    fd = open(filename, (0_RDWR | 0_CREAT), S_IWUSR);
    if (fd < 0) {
        perror("Couldn't create output file\n");
        return NULL;
    }
    if (ftruncate(fd, length)) {
        perror("Couldn't grow output file\n");
        close(fd);
        return NULL;
    }

    void *p = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
    if (p == -1) {
        perror("mmap failed");
        close(fd);
        return NULL;
    }
    close(fd);
    return p;
}

// now you've allocated your memory, you can populate it and it will be
// reflected in the file
于 2013-02-22T16:59:28.613 に答える
1

これはmmapのmanページからの抜粋です。

   On  success,  mmap() returns a pointer to the mapped area.  On error, the value
   MAP_FAILED (that is, (void *) -1) is returned, and errno is set  appropriately.
   On  success,  munmap()  returns 0, on failure -1, and errno is set (probably to
   EINVAL).

成功のテストは、mmapの-1の戻り値をテストするように変更する必要があります。次に、errno値を確認します。HTH。

于 2013-02-22T16:53:22.067 に答える