C 如何获得mmap';是否已删除要同步到文件的内存?
我正在为我的postscript解释器构建一个内存管理器,我希望它能够将会话挂起到磁盘并恢复保存的会话。我用一个匿名的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
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。是的<代码>地图共享做到了。谢谢