Pergunta

Aqui está a coisa: Eu tenho dois aplicativos, escrito em C ++ e em execução em duas máquinas com sistema operacional diferente (um Linux e um Windows). Um deste processo é responsável pela atualização de um arquivo XML em um (Network Attached Storage) NAS enquanto o outro lê este arquivo.

É possível sincronizar esses dois processos, a fim de evitar a leitura do arquivo, ao mesmo tempo ele está sendo modificado?

Foi útil?

Solução

Você pode criar um arquivo de bloqueio no servidor que é criado antes de fazer uma gravação, esperar em seguida, escrever e apagar na conclusão., Tem a verificação de processo de leitura para o token antes de ler o arquivo.

Editar : Para lidar com os comentários, você pode implementar um padrão tipo double-checked locking. Ter tanto leitor e escritor tem um arquivo de bloqueio e verifique antes de fazer o trabalho, algo como:

Leitor:. Verificar arquivo de bloqueio de gravação, criar arquivo de bloqueio de leitura, verificação de arquivo de bloqueio de gravação, se existe arquivo de leitura de exclusão e abort

Escritor:. Verificar arquivo de bloqueio de leitura, criar arquivo de bloqueio de gravação, verifique se há arquivo de bloqueio de leitura, se existe arquivo de exclusão escrita de bloqueio e abort

Isto irá parar seus processos pisotear uns aos outros, mas uma condição de corrida potencial pode ocorrer em que o que você poderia potencialmente ter ambos os processos verificar, criar, em seguida, verifique novamente simultaneamente embora isso não irá causar os dados para ser lido em um estado inconsistente, mas vai causar ambos os processos de leitura e gravação para abortar para o seu atraso especificado

Outras dicas

Obrigado a todos por suas respostas.

Por fim, conseguimos resolver o nosso problema, não utilizando comandos de bloqueio do sistema operacional (porque não tínhamos certeza que iria propagar corretamente para o OS da cabeça NAS), mas através da criação de diretórios de bloqueio em vez de arquivos de bloqueio. criação Directory é uma operação atômica, e retorna um valor de erro se a pasta já existe. Portanto, não temos de verificar a existência de bloqueio antes de adquiri-lo, ambas as operações são feitas em uma única etapa.

OK você precisa de alguma forma de mecanismo de bloqueio de acessos de controle.

A maioria dos sistemas nix arquivo * fornecer este. Eu suspeito que também está disponível no Windows File System (como este mecanismo é utilizado por perl), mas ele pode ter outro nome.

Dê uma olhada no rebanho ().
Este é um mecanismo de bloqueio de ficheiros. É um bloqueio consultivo para que ele não realmente bloquear o arquivo e impedir o uso, mas ele fornece um mecanismo para marcar o arquivo. Se ambos os aplicativos usam o mecanismo, em seguida, você pode controlar acessos para o arquivo.

flock () fornece ambos os bloqueios compartilhados (ou LEIA Lock) e bloqueios exclusivos (ou bloqueio de gravação). rebanho irá bloquear seu segmento (de forma não ocupado) até que o arquivo foi desbloqueado pelo usuário (que também fornece NON bloqueando cheques para que você possa fazer outras coisas enquanto espera).

Confira rebanho na secção 2 das páginas man.

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.

Se os arquivos residem em um NFS compartilhar você pode usar fcntl (2) para bloquear o arquivo. Verifique questão D10 na Linux NFS FAQ . Eu tenho muito pouca experiência com APIs do Windows, mas pelo que eu ouvi que eles têm um bom suporte POSIX por isso você deve ser capaz de usar fcntl enquanto eles apoiar POSIX.1-2001.

Se você estiver acessando os arquivos usando protocolos diferentes (ou seja AFS ou SMB) talvez você poderia configurar um servidor de sincronização simples que gerencia bloqueios através de uma interface IPC?

Seria possível mudar de arquivos em um banco de dados?

Este tipo de concurency é algo que SGBDs gerenciar muito bem. Ele não precisa ser caro ou difícil de instalar. MySql, Postgress ou JavaDB que todos lidar com isso elegantemente em pouco ou nenhum custo.

Na falta de opção de banco de dados que eu teria a gravação processo de escrita para um nome de arquivo "escondido" como ".updateinprogress.xml" e renomeie o arquivo quando a atualização for concluída. Na maioria dos sistemas "mv" ou "Ren" é uma operação atômica de modo que o processo de leitura tanto pega hte arquivo antigo ou o arquivo mais recente, mas nunca uma meia escrito um.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top