O inotify aciona uma notificação quando uma gravação é iniciada ou quando é concluída?

12

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_MODIFYno arquivo. O Writer grava 1000 bytes no arquivo, em uma única write()chamada. O Reader obtém o evento inotify e chama fstato arquivo. O que o Reader vê?

  1. Existe alguma garantia de que o Reader receberá pelo menos 1000 st_sizeno arquivo? Pelas minhas experiências, parece que não.

  2. 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, sarmostra 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 state 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.

Todd Freed
fonte
Você pode usar um pipe em vez de um arquivo. Veja man mknod
daniel kullmann
Precisamos usar um arquivo regular para ter um buffer de vários terabytes entre os dois processos. Também para preservar dados no buffer durante a reinicialização.
Todd Freed

Respostas:

5

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 o writesyscall: 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:

  • Talvez o leitor esteja recebendo notificações antigas, da gravação anterior.
  • Se o leitor ligar state depois ligar readou vice-versa, algo pode acontecer no meio. Se você continuar anexando ao arquivo, a ligação statprimeiro garante que você poderá ler até agora, mas é possível que mais dados tenham sido gravados quando o leitor ligar read, mesmo que ainda não tenha recebido a notificação de inotificação.
  • Só porque o escritor chama writenã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. writePoré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 da writechamada. Se você observar um arquivo parcialmente gravado, isso significa que writeretornou menos que seu argumento de tamanho.

Ferramentas úteis para investigar o que está acontecendo incluem:

  • strace -tt
  • o subsistema auditd
Gilles 'SO- parar de ser mau'
fonte
Obrigado pelas idéias. Acabei de revisar o código e, na verdade, só estou verificando -1 como o valor de retorno da gravação para o caso de erro. Portanto, pode ser que eu não esteja obtendo o valor de retorno da gravação indicando que todos os dados foram gravados. No entanto, quando olho o arquivo depois do fato, sei que todos os "1000" bytes foram gravados, porque o arquivo está em boa forma, ou seja, consiste em registros inteiros e coerentes. Portanto, o primeiro registro não está sendo parcialmente escrito.
Todd Freed