Imagine dois processos, um leitor e um escritor, se comunicando através de um arquivo regular em um ext3 fs. O Reader tem uma inspeção inotify IN_MODIFY
no arquivo. O Writer grava 1000 bytes no arquivo, em uma única write()
chamada. O Reader obtém o evento inotify e chama fstat
o arquivo. O que o Reader vê?
Existe alguma garantia de que o Reader receberá pelo menos 1000
st_size
no arquivo? Pelas minhas experiências, parece que não.Existe alguma garantia de que o Reader possa realmente
read()
1000 bytes?
Isso está acontecendo em uma caixa vinculada de E / S seriamente. Por exemplo, sar
mostra um tempo de espera de cerca de 1 segundo. No meu caso, o Reader está realmente aguardando 10 segundos APÓS obter o evento inotify antes de ligar stat
e obtendo resultados muito pequenos.
O que eu esperava era que o evento inotify não fosse entregue até que o arquivo estivesse pronto. O que eu suspeito que realmente está acontecendo é que o evento inotify é acionado DURANTE a write()
chamada no Writer e os dados estão realmente disponíveis para outros processos no sistema sempre que estiverem prontos. Nesse caso, 10s não é tempo suficiente.
Acho que estou apenas procurando por confirmação de que o kernel realmente implementa inotificar a maneira como estou adivinhando. Além disso, se houver alguma opção, possivelmente, para alterar esse comportamento?
Finalmente - qual é o sentido de inotificar, dado esse comportamento? Você está reduzido a pesquisar o arquivo / diretório de qualquer maneira, depois de receber o evento, até que os dados estejam realmente disponíveis. Pode muito bem estar fazendo isso o tempo todo e esquecer a inotificação.
*** EDITAR ** * * Ok, como muitas vezes acontece, o comportamento que estou vendo realmente faz sentido, agora que entendo o que estou realmente fazendo. ^ _ ^
Na verdade, estou respondendo a um evento IN_CREATE no diretório em que o arquivo está. Então, na verdade, estou stat () 'o arquivo em resposta à criação do arquivo, não necessariamente o evento IN_MODIFY, que pode estar chegando mais tarde.
Vou alterar meu código para que, depois de obter o evento IN_CREATE, assine IN_MODIFY no próprio arquivo e não tentarei ler o arquivo até obter o evento IN_MODIFY. Percebo que existe uma pequena janela na qual posso perder uma gravação no arquivo, mas isso é aceitável para o meu aplicativo, porque, na pior das hipóteses, o arquivo será fechado após um número máximo de segundos.
Respostas:
Pelo que vejo na fonte do kernel , o inotify é acionado somente após a conclusão da gravação (ou seja, seu palpite está errado). Depois que a notificação é acionada, apenas duas coisas acontecem
sys_write
, a função que implementa owrite
syscall: definindo alguns parâmetros do planejador e atualizando a posição no descritor de arquivo. Este código foi semelhante já em 2.6.14 . Quando a notificação é acionada, o arquivo já possui seu novo tamanho.Verifique se há coisas que podem dar errado:
stat
e depois ligarread
ou vice-versa, algo pode acontecer no meio. Se você continuar anexando ao arquivo, a ligaçãostat
primeiro garante que você poderá ler até agora, mas é possível que mais dados tenham sido gravados quando o leitor ligarread
, mesmo que ainda não tenha recebido a notificação de inotificação.write
não significa que o kernel gravará o número solicitado de caracteres. Existem muito poucas circunstâncias em que as gravações atômicas são garantidas para qualquer tamanho.write
Porém, cada chamada é atômica garantida: em algum momento os dados ainda não foram gravados e, de repente, n bytes foram gravados, onde n é o valor de retorno dawrite
chamada. Se você observar um arquivo parcialmente gravado, isso significa quewrite
retornou menos que seu argumento de tamanho.Ferramentas úteis para investigar o que está acontecendo incluem:
strace -tt
fonte