Ошибка шины после успеха mmap

Контекст

  • Linux 4.4.0-57-generic #78-Ubuntu SMP Пт, 9 декабря, 23:50:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
  • Французская локаль

Код

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>

int main() {
   int fd = open( "/tmp/mapped.bin", O_CREAT|O_RDWR|O_SYNC, 0666 );
   perror("open");
   unsigned char * dst =
      (unsigned char *)mmap(
         NULL, 64*1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
   perror("mmap");
   static unsigned char src[] = { 1, 3, 5, 7 };
   printf("memcpy( %p, {%d,%d,%d,%d}, %zd )\n", dst, src[0], src[1], src[2], src[3], sizeof(src));
   memcpy(dst, src, sizeof(src));
   perror("memcpy");
   return 0;
}

Производство

$ gcc -W -Wall -std=c11 src/org/hpms/filemap/BusError.c -o bin/BusError
(no warning, no error)

Выполнение

$ bin/BusError
open: Success
mmap: Success
memcpy( 0x7f51291fe000, {1,3,5,7}, 4 )
Erreur du bus

gdb

(gdb) run
Starting program: /home/aubin/Dev/Java/2017/org.hpms.filemap/bin/BusError
open: Success
mmap: Success
memcpy( 0x7ffff7fe6000, {1,3,5,7}, 4 )

Program received signal SIGBUS, Bus error.
0x00000000004005ac in main () at src/org/hpms/filemap/BusError.c:15
15     memcpy(dst, src, sizeof(src));
(gdb)

person Aubin    schedule 29.05.2017    source источник
comment
typedef byte bytes_t вводит в заблуждение. Также обратите внимание, что POSIX резервирует имена, оканчивающиеся на _t; вы не должны их использовать. Если вам нужны байты, используйте unsigned char напрямую и не typedef скрывайте такие псевдонимы. Если вам нужны 8-битные типы, используйте тип фиксированной ширины uint8_t. Сказал, что: имея почти 10 тысяч представителей, вы должны знать Как спросить и предоставить минимальный воспроизводимый пример! Что возвращают функции? Как насчет ошибок? ...   -  person too honest for this site    schedule 29.05.2017


Ответы (1)


Вы получите SIGBUS, если получите доступ к mmaped-памяти вне файла. Другими словами, если вы хотите записать 4 байта, размер файла должен быть не менее 4 байт.

В вашем примере вы можете решить проблему с ftruncate:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int main() {
   int fd = open( "/tmp/mapped.bin", O_CREAT|O_RDWR|O_SYNC, 0666 );
   perror("open");
   unsigned char * dst =
      (unsigned char *)mmap(
         NULL, 64*1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
   perror("mmap");
   static unsigned char src[] = { 1, 3, 5, 7 };
   ftruncate(fd, sizeof src);
   perror("ftruncate");
   printf("memcpy( %p, {%d,%d,%d,%d}, %zd )\n", dst, src[0], src[1], src[2], src[3], sizeof(src));
   memcpy(dst, src, sizeof(src));
   perror("memcpy");
   return 0;
}
person PSkocik    schedule 29.05.2017
comment
Вы действительно должны сделать размер файла кратным 4K, то есть размеру страницы, если можете. Это упрощает все управление памятью. - person Zan Lynx; 30.05.2017