0

Postscript インタプリタ用のメモリ マネージャを構築しています。ディスクへのセッションを一時停止し、保存されたセッションを再開できるようにしたいと考えています。匿名を使用して設計しましたmmapが、すべてが機能しているようです。テスト コードでは、メモリへのアクセスに問題はないようです。しかしMAP_ANONYMOUS、ファイル記述子を削除して提供したO_RDWRので、テストの実行後にファイル内のメモリの内容を確認できません。

#include <stdlib.h> /* exit free malloc realloc */
#include <stdio.h> /* fprintf printf perror */
#include <string.h> /* memset */
#include <unistd.h> /* getpagesize */

#include <sys/stat.h> /* open */
#include <fcntl.h> /* open */

/* placeholder error function */
/* ultimately, this will do a longjmp back to the central loop */
void error(char *msg) {
    fprintf(stderr, "%s\n", msg);
    perror("last system error:");
    exit(EXIT_FAILURE);
}

unsigned pgsz /*= getpagesize()*/; /*=4096 (usually on 32bit)*/

/*
typedef struct {
    unsigned char *base;
    unsigned used;
    unsigned max;
} mfile;
*/

/* dump mfile details to stdout */
void dumpmfile(mfile *mem){
    printf("{mfile: base = %p, "
            "used = 0x%x (%u), "
            "max = 0x%x (%u)}\n",
            mem->base,
            mem->used, mem->used,
            mem->max, mem->max);
    unsigned u;
    for (u=0; u < mem->used; u++) {
        if (u%16 == 0) {
            printf("\n%06u %04x: ", u, u);
        }
        printf("%02x ", (unsigned) mem->base[u]);
    }
    puts("");
}

/* memfile exists in path */
int getmemfile(){
    int fd;
    fd = open(
            "x.mem",
            O_RDWR);
    return fd;
}


/* initialize the memory file */
void initmem(mfile *mem){
    int fd;
    struct stat buf;
    size_t sz = pgsz;

    fd = getmemfile();
    if (fd != -1){
        fstat(fd, &buf);
        sz = buf.st_size;
        if (sz < pgsz) sz = pgsz;
    }

#ifdef MMAP
    mem->base = mmap(NULL,
            sz,
            PROT_READ|PROT_WRITE,
            MAP_PRIVATE
# ifndef MREMAP
            |MAP_AUTOGROW
# endif
            | (fd == -1? MAP_ANONYMOUS : 0) , fd, 0);
    if (mem->base == MAP_FAILED)
#else
    mem->base = malloc(pgsz);
    if (mem->base == NULL)
#endif
        error("unable to initialize memory file");
    mem->used = 0;
    mem->max = pgsz;
}

/* destroy the memory file */
void exitmem(mfile *mem){
#ifdef MMAP
    munmap(mem->base, mem->max);
#else
    free(mem->base);
#endif
    mem->base = NULL;
    mem->used = 0;
    mem->max = 0;
}

// ... omitting some address table functions not relevant here.


mfile mem;

/* initialize everything */
void init(void){
    pgsz = getpagesize();
    initmem(&mem);
    (void)initmtab(&mem); /* create mtab at address zero */
}

void xit(void){
    exitmem(&mem);
}

int main(){
    init();
    unsigned ent;
    int seven = 7;
    int ret;

    //printf("getmemfile: %d\n", getmemfile());

    ent = mtalloc(&mem, 0, sizeof seven);
    put(&mem, ent, 0, sizeof seven, &seven);
    get(&mem, ent, 0, sizeof seven, &ret);
    printf("put %d, got %d\n", seven, ret);

    unsigned ent2;
    ent2 = mtalloc(&mem, 0, 8*sizeof seven);
    put(&mem, ent2, 6, sizeof seven, &seven);
    get(&mem, ent2, 6, sizeof seven, &ret);
    printf("put %d in slot 7, got %d\n", seven, ret);
    //get(&mem, ent2, 9, sizeof seven, &ret);
    //printf("attempted to retrieve element 10 from an 8-element array, got %d\n", ret);

    unsigned ent3;
    char str[] = "beads in buddha's necklace";
    char sret[sizeof str];
    ent3 = mtalloc(&mem, 0, strlen(str)+1);
    put(&mem, ent3, 0, sizeof str, str);
    get(&mem, ent3, 0, sizeof str, sret);
    printf("stored and retrieved %s\n", sret);

    xit();
    return 0;
}

テストを実行し、ファイルをチェックします。

josh@Z1 ~/xpost
$ テストを行う
cc -g -Wall -Wextra -DTESTMODULE -om mc
./ob && ./m
7 を入れて 7 を得た
スロット 7 に 7 を入れて 7 を得た
ブッダのネックレスに保管され、取り出されたビーズ

josh@Z1 ~/xpost
$ od x.mem
0000000 000000 000000 000000 000000 000000 000000 000000 000000
*
0200000

josh@Z1 ~/xpost
$

どういうわけかそれをフラッシュする必要がありますか?またはファイルを閉じますか?おー。くそ、きっとそれじゃない?さて、これを入力するのにいくらかの労力を費やしたので、共有します。ローカライズされすぎている場合は、それで構いません。いいえ。close出力をまったく変更しません。

更新: 現在、すべてが機能しているようです。最後のいくつかの問題は、open() 呼び出しで O_CREAT を省略して、ファイル名をハードコーディングすることでした。そして、その他の小さな失敗。msync適切な措置のために追加しましたMAP_SHAREDが、上記の修正です。このモジュールと関連モジュールはhttp://code.google.com/p/xpost/source/browse/で表示できます。

4

1 に答える 1

1

MAP_PRIVATEメモリ領域に加えた変更を使用して物事をマップするため、プロセスにプライベートです。変更を他の人に見えるようにするには (ファイルへの書き込みとは)、 でマップする必要がありますMAP_SHARED

また、ファイルのサイズを で設定する必要がありますftruncate。それ以外の場合、mmaped 領域はファイルの存在しない部分をカバーするだけです。

データが最終的にディスク上にあることを本当に確認したい場合は、 を使用しmsyncますが、通常は、mmap:ed 領域に書き込んだ内容をすぐに見ることができます。統一されたバッファとオブジェクト キャッシュがありません。

于 2013-04-16T08:53:30.517 に答える