2010-05-10 15 views
9

En C++, hay un std::fwrite() que escribe un búfer en un archivo en el disco.¿Fwrite almacena en búfer la salida?

¿Puede decirme si hay algún buffer dentro de esa implementación de fwrite?

es decir, si llamo a fwrite() varias veces (digamos 10 veces), ¿realmente invoca E/S de archivo 10 veces diferentes?

Estoy pidiendo esto para el entorno Ubuntu 10.04.

Respuesta

10

Sí, está protegido. El tamaño del buffer está definido por BUFSIZ. (Gracias @ladenedge.) Diez operaciones suficientemente grandes darán como resultado diez llamadas al sistema.

También puede configurar su propio búfer usando std::setbuf y std::setvbuf.

Las funciones en cstdio se heredan de C. La interfaz preferida en C++ es fstream y filebuf.

+2

Creo que el tamaño del búfer predeterminado es 'BUFSIZ', como se define en stdio.h, aunque, por supuesto, los llamantes no deberían necesitar esa información. 'setbuf' se puede usar para controlar el tamaño en algunos sistemas. – ladenedge

+0

Lol, publicaste eso literalmente en el segundo exacto en que hice una edición: "ladenedge hace 1 segundo" – Potatoswatter

6

Depende. En la mayoría de las plataformas, el archivo IO se almacena en caché, por lo que existe la llamada fflush() para escribir datos en caché en el disco; en ese sentido, la respuesta a su primera pregunta es (normalmente) "sí" y su segundo "no". Dicho esto, no está garantizado que sea de esa forma por ningún lado de la imaginación para una plataforma en particular; en general, los estándares solo especifican la interfaz para tales funciones, no su implementación. Además, es bastante posible que al llamar al fwrite() se produzca una descarga implícita si la memoria caché se "llena", en cuyo caso llamar a fwrite() puede de hecho desencadenar el archivo IO, especialmente si llama al fwrite() con grandes cantidades de datos.

+1

Las funciones de IO de la biblioteca están almacenadas en el búfer, pero también suelen ser las funciones de IO del sistema; no solo eso, el controlador de disco también tiene un caché. En realidad, generalmente el problema con los discos no es asegurarse de que su salida se almacena en caché, sino asegurarse de que esté * realmente * escrito en el disco cuando lo necesite.:) –

+0

@Matteo, sé lo que quiere decir - por ejemplo, usando fwrite para escribir un registro de errores puede ser interesante si el programa se bloquea * antes * de los cachés se escriben en el disco. Afortunadamente, hay una fuga para eso ... – Mac

+0

"los estándares solo especifican la interfaz para tales funciones, no su implementación" no es precisa. Si bien el estándar no especifica la implementación, sí especifica el comportamiento. Y en este caso, el estándar especifica que FILE * está almacenado (C++ incorpora el estándar C en 17.3.1.4/1 y el estándar C define que FILE * está almacenado en 7.19.5.6/2). –

0

Depende de la implementación de la biblioteca. Puede echar un vistazo a algo como dtruss o strace para ver qué llamadas al sistema son realmente invocadas por la implementación.

¿Por qué te preocupas por esto?

+0

Mi programa está haciendo un montón de fwrite(). Y se ejecuta en Ubuntu 10.04. Me gustaría saber si necesito almacenar el IO antes de llamar a fwrite() por razones de rendimiento. – michael

+0

@michael: Sí, amortigua la E/S. Reducir el número de llamadas a 'fwrite' reducirá al mínimo la cantidad de ramas en su código. Las sucursales tienden a ralentizar el rendimiento ya que muchos procesadores vuelven a cargar su caché de instrucciones después de una rama. Además, menos código para ejecutar hace que un programa sea más rápido. –

+0

¿Por qué no solo perfila tu código para encontrar cuellos de botella? – WhirlWind

0

No creo que los estándares dicen nada sobre esto, pero en general: no el sistema operativo decidirá cuántas operaciones de E/S hacer. Podría ser 1 podría ser 10. Podría incluso ser más si el tamaño de los datos es grande. La mayoría de los sistemas operativos le permiten controlar el comportamiento de E/S, pero AFAIK no existe una forma portátil de hacerlo. (y a menudo no desea hacerlo de todos modos)

2

FILE* Las E/S pueden almacenarse en búfer pero no tiene que ser así (puede ser diferente para cada transmisión). Además, hay varias formas de hacer el almacenamiento en búfer (totalmente en búfer donde el búfer no se vacía hasta que esté lleno o cuando se realiza una llamada explícita al fflush o línea en búfer donde el búfer no se vacía hasta que ve un EOL). También es posible desactivar el almacenamiento en búfer por completo.

Puede cambiar el tipo de almacenamiento en búfer con la llamada setvbuf.

Cuestiones relacionadas