2011-09-26 11 views
13

Tengo un proceso abriendo un archivo en el modo de agregar. En este caso, es un archivo de registro. Código de ejemplo:¿Se pueden agregar procesos múltiples a un archivo usando fopen sin ningún problema de simultaneidad?

int main(int argc, char **argv) { 
    FILE *f; 
    f = fopen("log.txt", "a"); 
    fprintf(f, "log entry line"); 
    fclose(f); 
} 

Dos preguntas:

  1. Si tengo varios procesos anexas al mismo archivo, aparecerá claramente cada línea de registro o que puede ser entrelazado como el cambio de contexto procesos?
  2. ¿Escribirá este bloque si muchos procesos requieren acceso al archivo, por lo tanto, causa problemas de concurrencia?

Estoy considerando hacer esto en su versión más simple o usar zeromq para bombear las entradas de registro sobre las tuberías a un colector de registros.

Considero syslog pero realmente no quiero ninguna dependencia de la plataforma en el software.

La plataforma predeterminada es Linux para este btw.

Respuesta

5

Seguramente tendrá dependencias de plataforma, ya que Windows no puede manejar múltiples procesos que se anexan al mismo archivo.

En cuanto a problemas de sincronización, creo que la salida de buffer de línea/should/save la mayor parte del tiempo, es decir, más del 99,99% de las líneas de registro cortas deben estar intactas según mi prueba corta basada en shell, pero no siempre . La semántica explícita es definitivamente preferible, y ya que no podrás escribir este sistema de hack, independientemente de todos modos, recomendaría un enfoque syslog.

+0

Gracias - eso es justo lo que quería saber. El agregado múltiple de Windows es lo que me preocupaba un poco. – Deleted

3

Cuando los procesos se van a escribir algo como:

"Here's process #1" 
"Here's process #2" 

es probable que obtener algo como:

"Hehere's process #2re's process #1" 

Usted tendrá que sincronizarlos.

1

A menos que realice algún tipo de sincronización, las líneas de registro pueden superponerse. Entonces, para responder el número dos, eso depende de cómo implemente el código de bloqueo y registro. Si solo bloquea, escribe en el archivo y desbloquea, eso puede causar problemas si tiene muchos procesos tratando de acceder al archivo al mismo tiempo.

8

No sé fopen y fprintf pero puede open el archivo usando O_APPEND. Luego cada write irá al final del archivo sin ningún problema (sin mezclarse con otra escritura).

busca realmente en el standard:

El descriptor de fichero asociado con el flujo abierto se asigna y se abrió como por una llamada a abrir() con los siguientes banderas:

a or ab   O_WRONLY|O_CREAT|O_APPEND 

Así que supongo que es seguro para fprintf desde procesos múltiples, siempre y cuando el archivo se haya abierto con a.

+2

usted todavía tiene que cambiar el tampón para ninguna o una línea. Con el almacenamiento en búfer completo, puede quedarse sin búfer en el medio de la entrada y escribir con eso. –

+0

@ Jan Hudec Eso es correcto. Otra razón más para usar 'write (2)' directamente. – cnicutar

6

El standard (para abrir/escritura, no fopen/fwrite) afirma que

Si la bandera O_APPEND de los indicadores de estado del archivo se establece, el archivo de compensación se fijará al final del archivo antes para cada escritura y no se producirá ninguna operación de modificación de archivos entre cambios entre el cambio de archivo y la operación de escritura.

Para utilizar fprintf(), debe deshabilitar el almacenamiento en búfer del archivo.

+0

** Importante **: Eso es para 'abrir' /' escribir', * no * fopen/fwrite. –

+0

Derecha, pero 'write()' "se encuentra debajo de" 'fwrite()' y 'fprintf()', es decir, es utilizado por ellos. Si el almacenamiento en búfer está desactivado, incluso se usa 1: 1. (Pero mejor explíquelo, así que tiene razón.) – glglgl

+0

No es necesario deshabilitar el almacenamiento en búfer para que esto funcione. En realidad, el almacenamiento en línea ayuda a garantizar que las líneas completas se escriben a la vez –

2

EDITAR para responder a sus preguntas de forma explícita:

  1. Si tengo varios procesos anexas al mismo archivo, aparecerá claramente cada línea de registro o que puede ser entrelazado como el cambio de contexto procesos?

Sí, cada línea de registro aparecerá intacta porque según msdn/vs2010:

"Esta función [que es, fwrite()] bloquea el subproceso de la llamada y por lo tanto es seguro para subprocesos. Para un no -locking versión, consulte _fwrite_nolock "

El mismo está implícito en the GNU manpage:

" - Función:. fwrite size_t (const void * data, tamaño size_t , Recuento size_t, flujo FILE *)

This function writes up to count objects of size size from the array data, to the stream stream. The return value is normally count, if the call succeeds. Any other value indicates some sort of error, such as running out of space. 

- Función: size_t fwrite_unlocked (datos * const void, tamaño size_t, recuento size_t, FILE * stream)

The fwrite_unlocked function is equivalent to the fwrite function except that it does not implicitly lock the stream. 

This function [i.e., fwrite_unlocked()] is a GNU extension. " 
  1. Será este bloque de escritura si muchos procesos requieren acceso al archivo, por lo tanto, ¿causan problemas de concurrencia?

Sí, por implicación de la pregunta 1.

+0

Gracias por la respuesta.El problema potencial que tengo es la concurrencia, por lo que el bloqueo causará problemas con eso. He votado como el caso de uso sigue siendo válido y descriptivo. ¡Gracias de nuevo! – Deleted

+0

Oh, finalmente lo entiendo. Por "problema de concurrencia", tiene miedo de que process2 se bloquee mientras que process1 intenta escribir en el archivo de registro. Edité mi respuesta para abordar ambas preguntas de manera explícita. –

+0

Esa es la :) :) gracias de nuevo por su respuesta de todos modos. Yo usaría esto en requisitos de concurrencia baja. – Deleted

Cuestiones relacionadas