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/で表示できます。