Чтение файла в строку с помощью mmap

Я пытаюсь прочитать файл в строке с помощью mmap.

Я следовал этому примеру: http://www.lemoda.net/c/mmap-example/index.html

Мой код выглядит так:

unsigned char *f; int size; int main(int argc, char const *argv[]) { struct stat s; const char * file_name = argv[1]; int fd = open (argv[1], O_RDONLY); /* Get the size of the file. */ int status = fstat (fd, & s); size = s.st_size; f = (char *) mmap (0, size, PROT_READ, 0, fd, 0); for (i = 0; i < size; i++) { char c; c = f[i]; putchar(c); } return 0; } 

Но при доступе к f [i] я всегда получаю ошибку segemation. Что я делаю неправильно?

strace – ваш друг здесь:

$ strace ./mmap-example mmap-example.c

 ... ... (lots of output) ... open("mmap-example.c", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=582, ...}) = 0 mmap(NULL, 582, PROT_READ, MAP_FILE, 3, 0) = -1 EINVAL (Invalid argument) --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV +++ 

На странице mmap рассказывается все, что вам нужно знать;)

  • EINVAL Нам не нравятся addr , length или offset (например, они слишком большие или не выровнены на границе страницы).
  • length EINVAL (начиная с Linux 2.6.12) length 0.
  • flags EINVAL содержали ни MAP_PRIVATE ни MAP_SHARED , ни
    содержали оба эти значения.

Ошибка -EINVAL вызвана флагами, которые не могут быть MAP_PRIVATE 0. MAP_PRIVATE MAP_SHARED MAP_PRIVATE или MAP_SHARED . Я смог заставить его работать, используя MAP_PRIVATE в Linux, x86-64.

Итак, вы должны добавить MAP_PRIVATE в mmap() :

 #include  #include  #include  #include  #include  #include  #include  int main(int argc, char const *argv[]) { unsigned char *f; int size; struct stat s; const char * file_name = argv[1]; int fd = open (argv[1], O_RDONLY); /* Get the size of the file. */ int status = fstat (fd, & s); size = s.st_size; f = (char *) mmap (0, size, PROT_READ, MAP_PRIVATE, fd, 0); for (int i = 0; i < size; i++) { char c; c = f[i]; putchar(c); } return 0; } 

ПРИМЕЧАНИЕ. Мой первый ответ включал еще одну возможную причину для EINVAL :

size должен быть целым, кратным размеру страницы системы. Чтобы получить размер страницы, используйте функцию getpagesize() .

Это на самом деле не требуется , но вы должны учитывать, что в любом случае отображение всегда будет выполняться в кратном размере системной страницы, поэтому, если вы хотите рассчитать, сколько памяти действительно доступно через возвращаемый указатель, обновите size :

 int pagesize = getpagesize(); size = s.st_size; size += pagesize-(size%pagesize);