Почему fopen/fgets используют как mmap, так и системные вызовы для доступа к данным?
У меня есть небольшая примерная программа, которая просто fopen
файл и использует fgets
для ее чтения. Используя strace
, я заметил, что первый вызов fgets
запускает системный вызов mmap
, а затем чтение системных вызовов используется для фактического чтения содержимого файла. на fclose
, файл munmap
ed. Если я вместо этого прочитаю файл с открытым/прочитанным напрямую, это, очевидно, не произойдет. Мне интересно, какова цель этого 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
Ответы
Ответ 1
Это не файл mmap
'ed - в этом случае mmap
используется анонимно (не в файле), возможно, для выделения памяти для буфера, который будут использоваться последующие чтения.
malloc
фактически приводит к такому призыву к mmap
. Аналогично, munmap
соответствует вызову free
.
Ответ 2
mmap
не отображает файл; вместо этого он выделяет память для буферизации stdio FILE
. Обычно malloc
не будет использовать mmap
для обслуживания такого небольшого выделения, но, похоже, реализация glibc stdio использует mmap
непосредственно для получения буфера. Вероятно, это необходимо для выравнивания по страницам (хотя posix_memalign
мог бы достичь того же) и/или убедиться, что закрытие файла возвращает буферную память в ядро. Я сомневаюсь в полезности выравнивания по страницам буфера. Предположительно это для производительности, но я не вижу никакого способа помочь, если только смещение файла, которое вы читаете, также выровнено по страницам, и даже тогда это кажется сомнительной микро-оптимизацией.
Ответ 3
из того, что я читал, функции сопоставления памяти полезны при обработке больших файлов. теперь определение большого - это то, о чем я понятия не имею. но да для больших файлов они значительно быстрее по сравнению с "буферизованными" вызовами ввода/вывода.
в примере, который вы опубликовали, я думаю, что файл открывается функцией open()
, а mmap используется для выделения памяти или чего-то еще.
из синтаксиса функции mmap это ясно видно:
void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
второй последний параметр принимает дескриптор файла, который должен быть неотрицательным.
в то время как в трассировке стека это -1