C 如何获得mmap';是否已删除要同步到文件的内存?

C 如何获得mmap';是否已删除要同步到文件的内存?,c,memory-management,posix,interpreter,mmap,C,Memory Management,Posix,Interpreter,Mmap,我正在为我的postscript解释器构建一个内存管理器,我希望它能够将会话挂起到磁盘并恢复保存的会话。我用一个匿名的mmap设计了它,看起来一切都正常。测试代码在访问内存时似乎没有问题。但是现在我已经删除了MAP\u ANONYMOUS并提供了一个O_RDWR文件描述符,在测试运行后,我看不到文件中的内存内容 #include <stdlib.h> /* exit free malloc realloc */ #include <stdio.h> /* fprintf

我正在为我的postscript解释器构建一个内存管理器,我希望它能够将会话挂起到磁盘并恢复保存的会话。我用一个匿名的
mmap
设计了它,看起来一切都正常。测试代码在访问内存时似乎没有问题。但是现在我已经删除了
MAP\u 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;
}
#包括/*退出自由malloc realloc*/
#包括/*fprintf printf peror*/
#include/*memset*/
#include/*getpagesize*/
#包括/*开放*/
#包括/*开放*/
/*占位符错误函数*/
/*最终,这将做一个长的JMP返回到中央循环*/
无效错误(字符*消息){
fprintf(stderr,“%s\n”,msg);
perror(“上次系统错误:”);
退出(退出失败);
}
无符号pgsz/*=getpagesize()*//*=4096(通常为32位)*/
/*
类型定义结构{
无符号字符*基;
未签名的使用;
无符号最大值;
}mfile;
*/
/*将mfile详细信息转储到标准输出*/
无效转储文件(mfile*mem){
printf(“{mfile:base=%p,”
已使用=0x%x(%u)
“max=0x%x(%u)}\n”,
mem->base,
mem->used,mem->used,
mem->max,mem->max);
未签名的u;
对于(u=0;uused;u++){
如果(u%16==0){
printf(“\n%06u%04x:,u,u);
}
printf(“%02x”,无符号)mem->base[u];
}
认沽权(“”);
}
/*memfile存在于路径中*/
int getmemfile(){
int-fd;
fd=打开(
“x.mem”,
O_RDWR);
返回fd;
}
/*初始化内存文件*/
void initmem(mfile*mem){
int-fd;
结构统计buf;
尺寸_t sz=pgsz;
fd=getmemfile();
如果(fd!=-1){
财政司司长(财政司司长和财政司司长);
sz=buf.st_尺寸;
如果(szbase=mmap(空,
sz,
保护读,保护写,
私人地图
#ifndef MREMAP
|地图自动增长
#恩迪夫
|(fd==-1?映射:0),fd,0);
if(mem->base==MAP\u失败)
#否则
mem->base=malloc(pgsz);
如果(mem->base==NULL)
#恩迪夫
错误(“无法初始化内存文件”);
mem->used=0;
mem->max=pgsz;
}
/*销毁内存文件*/
void exitmem(mfile*mem){
#ifdef MMAP
munmap(mem->base,mem->max);
#否则
免费(mem->base);
#恩迪夫
mem->base=NULL;
mem->used=0;
mem->max=0;
}
// ... 省略此处不相关的一些地址表函数。
mfilemem;
/*初始化一切*/
void init(void){
pgsz=getpagesize();
initmem(&mem);
(void)initmtab(&mem);/*在地址0处创建mtab*/
}
void xit(void){
exitmem(&mem);
}
int main(){
init();
未签名的ent;
int七=7;
int ret;
//printf(“getmemfile:%d\n”,getmemfile());
ent=mtalloc(&mem,0,大小为七);
放置(&mem、ent、0、七个大小和七个大小);
获取(&mem,ent,0,sizeof seven,&ret);
printf(“放%d,得到%d\n”,七,ret);
未签名ent2;
ent2=mtalloc(&mem,0,8*sizeof seven);
放置(&mem,ent2,6,sizeof seven,&seven);
获取(&mem、ent2、6、sizeof seven和ret);
printf(“将%d放入插槽7,得到%d\n”,第七,ret);
//获取(&mem、ent2、9、sizeof seven和ret);
//printf(“试图从8元素数组中检索元素10,得到%d\n”,ret);
未签名ent3;
char str[]=“佛珠项链”;
char sret[sizeof str];
ent3=mtalloc(&mem,0,strlen(str)+1);
put(&mem,ent3,0,sizeof str,str);
获取(&mem,ent3,0,sizeof str,sret);
printf(“存储和检索的%s\n”,sret);
xit();
返回0;
}
运行测试,检查文件

josh@Z1 ~/xpost $ make test cc -g -Wall -Wextra -DTESTMODULE -o m m.c ./ob && ./m put 7, got 7 put 7 in slot 7, got 7 stored and retrieved beads in buddha's necklace josh@Z1 ~/xpost $ od x.mem 0000000 000000 000000 000000 000000 000000 000000 000000 000000 * 0200000 josh@Z1 ~/xpost $ josh@Z1~/xpost $make测试 cc-g-Wall-Wextra-DTESTMODULE-o m.c /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 $ 我需要冲洗一下吗?还是关闭文件?哦废话,我打赌就是这样,不是吗?好吧,我花了一些精力来输入这个,所以我将与大家分享。如果它太本地化,那就这样吧。没有<代码>关闭根本不会更改输出


更新:现在一切似乎都在运转。最后几个问题是硬编码文件名,在open()调用中省略了O_create。以及其他一些小错误。我添加了
msync
作为良好的度量,但是
MAP\u SHARED
是对上述问题的修复。此模块和相关模块可在中查看。

因为您使用
map\u PRIVATE
映射事物,所以对内存区域所做的更改对您的进程是私有的。要使更改对任何其他人可见(写入文件是什么),您需要使用
map\u SHARED
进行映射

此外,还需要使用
ftruncate
设置文件大小。否则,mmaped区域只覆盖文件中不存在的部分


如果您确实想确保数据在磁盘上结束,请使用
msync
,但通常您可以立即看到写入mmap:ed区域的内容,除非您使用的是少数没有统一缓冲区和对象缓存的操作系统之一。

确定。这是有道理的。早些时候,当后来的mremap(…MAP_MAYMOVE)决定移动时,我遇到了地图共享出错的问题。但我正在Cygwin上重建,那里没有mremap。是的<代码>地图共享做到了。谢谢