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;
}

运行测试,检查文件。

乔什@Z1 ~/xpost
$ 进行测试
cc -g -Wall -Wextra -DTESTMODULE -om mc
./ob && ./m
放 7,得到 7
将 7 放入插槽 7,得到 7
佛项链中的珠子储存和取回

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

乔什@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. 否则,映射区域只会覆盖文件中不存在的部分。

如果您真的想确保数据最终保存在磁盘上,请使用msync,但通常您将能够立即看到写入 mmap:ed 区域的内容,除非您使用的是少数几个不支持的操作系统之一'没有统一的缓冲区和对象缓存。

于 2013-04-16T08:53:30.517 回答