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.


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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.