2013-09-29 3 views
1

Я пытаюсь воспроизвести работу mremap, чтобы вырастить mmap'ed память/файл. Я грубо следовал this example, но он предназначен для анонимных карт, тогда как я хочу, чтобы он был именованным файлом (это интерпретатор языка программирования, поэтому этот файл служит эквивалентом «основного дампа» состояния интерпретатора).reimplementing mremap в cygwin, новое пространство недоступно для записи

Оригинал трудно прочитать из-за гнездования # if-блоков. Так что это «извлеченный», но реальный код (для пути компиляции я отлаживаю). Полный источник может быть просмотрен here, но он не содержит этот код, потому что он не был зафиксирован, потому что он не работает. :) Однако версия mremap существует, а также резерв malloc.

unsigned pgsz /*= getpagesize()*/ = 4096; 

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

/* reallocate and possibly move mem->base */ 
mfile *growmem(mfile *mem, 
       unsigned sz) 
{ 
    void *tmp; 
    int newfd; 

    printf("growmem: %p %u + %u\n", mem->base, mem->max, sz); 
    if (sz < pgsz) sz = pgsz; 
    else sz = (sz/pgsz + 1) * pgsz; 
    sz += mem->max; 
    printf("growmem: new size: %u\n", sz); 

    msync(mem->base, mem->used, MS_SYNC); 
    newfd = dup(mem->fd); 
    tmp = mmap(NULL, sz, 
      PROT_READ|PROT_WRITE, 
      MAP_SHARED | (mem->fd == -1? MAP_ANONYMOUS : 0), 
      newfd, 0); 

    if (tmp == MAP_FAILED) 
     error(VMerror, "unable to grow memory"); 

    memcpy(tmp, mem->base, mem->used); 
    munmap(mem->base, mem->max); 
    mem->fd = newfd; 

    mem->base = tmp; 
    mem->max = sz; 
    return mem; 
} 

Это похоже на работу при вызове, но программа выйдет позже. Я не отслеживал точно, где, но на основе отслеживания основного цикла eval он очень похож на то, что новая часть памяти недоступна для записи. Оператор, который не выполняет выделение нового словарного объекта. И я подозреваю, что сделал что-то глупо, повторно используя тот же дескриптор файла. изменить: новый файловый дескриптор, тот же segfault.

Breakpoint 2, eval (ctx=0x80049a70) at src/bin/itp.c:482 
482   object t = top(ctx->lo, ctx->es, 0); 
(gdb) 
Continuing. 
evalload <name "dict"> 
eval 
Executing: <operator 24> 
Stack: 0:<integer 1>1:<integer 0>2:<integer 0>3:<integer 1>4:<integer 0>5:<integer 0>6:<array L 229 100 78 0>7:<integer 1>8:<dict L 102 16 658 0>9:<integer 8> 
Dict Stack: 0:<dict G 358 10 10 0>1:<dict G 358 100 188 0>2:<dict L 102 100 9 0>3:<dict G 486 24 310 0>4:<dict L 102 6 80 0> 
Exec Stack: 0:<operator 60>1:<array G 357 2 387 6>2:<boolean false>3:<array G 325 17 416 14>4:<operator 54>5:<operator 63>6:<array G 453 18 414 0>7:<array G 325 1 414 17>8:<array G 325 4 413 5>9:<boolean false>10:<file>11:<file>12:<array L 101 3 103 16>13:<array L 101 1 113 4>14:<operator 24> 
    2929 [main] itp 613952 exception::handle: Exception: STATUS_ACCESS_VIOLATION 
    10097 [main] itp 613952 open_stackdumpfile: Dumping stack trace to itp.exe.stackdump 





Program received signal SIGSEGV, Segmentation fault. 
0x61129ab9 in memset() from /usr/bin/cygwin1.dll 
(gdb) 
Continuing. 
warning: SuspendThread failed. (winerr 6) 
[Inferior 1 (process 613952) exited with code 0105400] 
(gdb) 

Отслеживается точная линия. При попытке коснуться какой-либо новой памяти она не работает при последующем распределении.

unsigned mfalloc(mfile *mem, 
       unsigned sz) 
{ 
    unsigned adr = mem->used; 

    if (sz) { 
     if (sz + mem->used >= mem->max) 
      mem = growmem(mem,sz); 
     mem->used += sz; 
     memset(mem->base+adr, 0, sz); //bzero(mem->base+adr, sz); 
     /* bus error with mremap(SHARED,ANON)! */ 
    } 
    return adr; 
} 

Что я делаю неправильно?

PS. У меня отключен отладчик прямо перед вызовом ошибки. Если бы какое-либо из значений переменной было бы полезно, я могу их получить. mem->fd равно 12, поэтому мы не сталкиваемся с той же ошибкой SHARED/ANON, с которой этот код сталкивался раньше, но в вызове mmap есть некоторая настройка, чтобы избежать этой комбинации.

Редактировать: Похоже, что доступ к старому содержимому памяти/файла не вызывает никаких проблем. Это новое пространство, которое невозможно использовать. Будет ли существующий открытый файл предотвратить большую смежную карту? Хм. Возможно, мне следовало бы msync, затем munmap, затем fdclose, , затем reopen и mmap. ... Это потребует некоторой редизайна, чтобы протестировать его, поскольку mfile struct должна будет хранить имя файла. ...

ответ

0

Похоже, что mmap Cygwin не будет автоматически увеличивать размер файла, если размер, запрошенный для карты, больше. Итак, ftruncate первый.

+0

Чтобы быть справедливым, это стандартное поведение; все реализации должны посылать сигнал SIGBUS в этом случае. – tne

+0

Я вижу. Но дебиан и Убунту позволили мне с этим справиться. Пока не пришло время для переноса кода. –

 Смежные вопросы

  • Нет связанных вопросов^_^