Tengo un pequeño programa de ejemplo que simplemente fopen
es un archivo y usa fgets
para leerlo. Usando strace
, noté que la primera llamada al fgets
ejecuta una llamada al sistema mmap
, y luego las llamadas al sistema de lectura se utilizan para leer el contenido del archivo. en fclose
, el archivo es munmap
ed. Si en cambio abro el archivo con abrir/leer directamente, obviamente esto no ocurre. Tengo curiosidad sobre cuál es el propósito de este mmap
y qué está logrando.¿Por qué fopen/fgets utiliza tanto mmap como las llamadas al sistema de lectura para acceder a los datos?
En mi sistema basado en Linux 2.6.31, cuando bajo mucha demanda de memoria virtual estos mmap
s a veces se cuelgan durante varios segundos, y me parece que no es necesario.
El código de ejemplo:
#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);
}
Y aquí está la salida relevante strace cuando se ejecuta el código anterior:
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
Interesante. Por lo tanto, de esto se deduce que todas las operaciones de lectura en FILE * realmente no se leen en el búfer proporcionado, sino en un búfer adicional asignado en el montón y luego se copian en mi búfer. Además, ¿malloc siempre da como resultado una llamada a mmap? Siempre pensé que Heap se administraba localmente en el espacio de usuario y las llamadas al sistema solo se realizaban si se necesitaba agregar más memoria al espacio de direcciones del proceso. También siempre pensé que sbrk/brk se usaba para esto, no para mmap. – bdk
@bdk: Sí, las funciones de archivo de la biblioteca estándar (no las llamadas al sistema) mantienen su propio búfer de forma que cuando se invoca 'fgets (buf, 1, f)' continuamente en un bucle, no da como resultado cientos de llamadas al sistema 'leer'. 'malloc' da como resultado un' mmap' cuando no tiene más espacio disponible en el espacio de usuario; por ejemplo, el primer 'malloc (8)' puede dar como resultado 'mmap (4096)', y consecuente 'malloc (8) '' devolverá punteros al área ya asignada hasta que se agote. –
Gracias! Eso lo explica. Cada vez que uso strace para intentar rastrear algo, termino aprendiendo algo nuevo. – bdk