Почему fopen / fgets использует системные вызовы mmap и read для доступа к данным? - PullRequest
10 голосов
/ 12 августа 2011

У меня есть небольшой пример программы, которая просто fopen s файл и использует fgets для его чтения. Используя strace, я замечаю, что первый вызов fgets запускает системный вызов mmap, а затем системные вызовы read используются для фактического чтения содержимого файла. на fclose файл munmap ред. Если я вместо этого открываю чтение файла с открытием / чтением напрямую, это, очевидно, не происходит. Мне любопытно, какова цель этого mmap и что он выполняет.

В моей системе, основанной на Linux 2.6.31, при большой нагрузке на виртуальную память эти mmap иногда зависают на несколько секунд и кажутся мне ненужными.

Пример кода:

#include <stdlib.h>
#include <stdio.h>
int main ()
{
   FILE *f;
   if ( NULL == ( f=fopen( "foo.txt","r" )))
   {
     printf ("Fail to open\n");
   }
   char buf[256];
   fgets(buf,256,f);
   fclose(f);
}

А вот соответствующий вывод strace при запуске приведенного выше кода:

open("foo.txt", O_RDONLY)               = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=9, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb8039000
read(3, "foo\nbar\n\n"..., 4096)        = 9
close(3)                                = 0
munmap(0xb8039000, 4096)                = 0

Ответы [ 3 ]

15 голосов
/ 12 августа 2011

Это не файл mmap 'ed - в этом случае mmap используется анонимно (не для файла), вероятно, для выделения памяти для буфера, который будет использовать последующее чтение.*malloc фактически приводит к такому вызову mmap.Аналогичным образом, munmap соответствует вызову free.

5 голосов
/ 13 августа 2011

mmap не отображает файл; вместо этого он выделяет память для буферизации stdio FILE. Обычно malloc не использует mmap для обслуживания такого небольшого выделения, но кажется, что реализация stdio в glibc использует mmap напрямую для получения буфера. Это, вероятно, для обеспечения выравнивания страницы (хотя posix_memalign может достичь того же самого) и / или для гарантии того, что закрытие файла возвращает буферную память ядру. Я подвергаю сомнению полезность выравнивания страницы в буфере. Предположительно это связано с производительностью, но я не вижу, как это могло бы помочь, если только смещение файла, с которого вы читаете, также не выровнено по страницам, и даже тогда это кажется сомнительной микрооптимизацией.

1 голос
/ 13 августа 2011

из того, что я прочитал, функции отображения памяти полезны при работе с большими файлами.Теперь определение большого - это то, о чем я понятия не имею.но да, для больших файлов они значительно быстрее по сравнению с «буферизованными» вызовами ввода / вывода.

в примере, который вы разместили, я думаю, что файл открывается функцией open(), а mmapиспользуется для выделения памяти или чего-то еще.

из синтаксиса функции mmap это ясно видно:

void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);

второй последний параметр принимает дескриптор файла, которыйдолжно быть неотрицательным.в то время как в трассировке стека это -1

...