Pregunta

Aquí está la cosa: tengo dos aplicaciones, escritas en C ++ y que se ejecutan en dos máquinas con diferentes sistemas operativos (una Linux y una Windows). Uno de estos procesos está a cargo de actualizar un archivo XML en un NAS (almacenamiento conectado a la red) mientras que el otro lee este archivo.

¿Es posible sincronizar estos dos procesos para evitar la lectura del archivo al mismo tiempo que se modifica?

¿Fue útil?

Solución

Puede crear un archivo de bloqueo en el servidor que se crea antes de escribir, espere y luego escriba y elimine al finalizar. Haga que el proceso de lectura verifique el token antes de leer el archivo.

Editar : para abordar los comentarios, puede implementar un patrón de bloqueo doblemente verificado. Haga que tanto el lector como el escritor tengan un archivo de bloqueo y una doble verificación antes de trabajar, algo así como:

Lector: Verifique el archivo de bloqueo de escritura, cree el archivo de bloqueo de lectura, verifique el archivo de bloqueo de escritura, si existe, elimine el archivo de lectura y cancele.

Escritor: Verifique el archivo de bloqueo de lectura, cree el archivo de bloqueo de escritura, verifique el archivo de bloqueo de lectura, si existe, elimine el archivo de bloqueo de escritura y cancele.

Esto detendrá los procesos que se pisotean entre sí, pero puede ocurrir una posible condición de carrera en la que potencialmente podría hacer que ambos procesos verifiquen, creen y vuelvan a verificar simultáneamente, aunque esto no hará que los datos se lean en un estado inconsistente, pero hacer que los procesos de lectura y escritura se cancelen por el retraso especificado

Otros consejos

Gracias a todos por sus respuestas.

Finalmente logramos resolver nuestro problema, no usando comandos de bloqueo del sistema operativo (porque no estábamos seguros de que se propagarían correctamente al sistema operativo del cabezal NAS), sino creando directorios de bloqueo en lugar de archivos de bloqueo. La creación del directorio es una operación atómica y devuelve un valor de error si la carpeta ya existe. Por lo tanto, no tenemos que verificar la existencia del bloqueo antes de adquirirlo, ambas operaciones se realizan en un solo paso.

OK, necesita algún tipo de mecanismo de bloqueo para controlar los accesos.

La mayoría de los sistemas de archivos * nix proporcionan esto. Sospecho que también está disponible en el sistema de archivos de Windows (ya que este mecanismo lo usa Perl), pero puede tener otro nombre.

Echa un vistazo a la bandada ().
Este es un mecanismo de bloqueo de archivos. Es un bloqueo de aviso, por lo que no bloquea el archivo y evita su uso, pero proporciona un mecanismo para marcar el archivo. Si ambas aplicaciones usan el mecanismo, puede controlar los accesos al archivo.

flock () proporciona bloqueos compartidos (o READ Lock) y bloqueos exclusivos (o WRITE Lock). flock bloqueará su hilo (de manera no ocupada) hasta que el usuario haya desbloqueado el archivo (también proporciona comprobaciones de NO bloqueo para que pueda hacer otras cosas mientras espera).

Echa un vistazo a la bandada en la sección 2 de las páginas del manual.

int     flock(int fd, int operation);

Flock() applies or removes an advisory lock on the file associated with the file
descriptor fd.  A lock is applied by specifying an operation parameter that is
one of LOCK_SH or LOCK_EX with the optional addition of LOCK_NB.  To unlock an
existing lock operation should be LOCK_UN.

Si los archivos residen en un recurso compartido NFS, puede usar fcntl (2) para bloquear el archivo. Compruebe la pregunta D10 en las Preguntas frecuentes sobre Linux NFS . Tengo muy poca experiencia con las API de Windows, pero por lo que he escuchado, tienen una buena compatibilidad con POSIX, por lo que debería poder usar fcntl siempre que sean compatibles con POSIX.1-2001.

Si está accediendo a los archivos usando diferentes protocolos (es decir, AFS o SMB), ¿tal vez podría configurar un servidor de sincronización simple que administre los bloqueos a través de una interfaz IPC?

¿Sería posible cambiar de archivos a una base de datos?

Este tipo de concurencia es algo que los DBMS manejan muy bien. No necesita ser costoso o difícil de instalar. MySql, Postgress o JavaDB manejarían esto de manera elegante a bajo costo o sin costo.

Si falla la opción de la base de datos, el proceso de escritura escribiría en un " oculto " nombre de archivo como " .updateinprogress.xml " y cambie el nombre del archivo cuando se complete la actualización. En la mayoría de los sistemas "mv" o '' ren '' es una operación atómica, por lo que el proceso de lectura recoge el archivo antiguo o el archivo más nuevo, pero nunca medio escrito.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top