Inotify déclenche-t-il une notification au début ou à la fin d'une écriture?

12

Imaginez deux processus, un lecteur et un écrivain, communiquant via un fichier standard sur un ext3 fs. Le lecteur possède une IN_MODIFYveille inotify sur le fichier. Writer écrit 1000 octets dans le fichier, en un seul write()appel. Le lecteur obtient l'événement inotify et appelle fstatle fichier. Que voit Reader?

  1. Y a-t-il une garantie que Reader récupérera au moins 1000 pour st_sizele fichier? D'après mes expériences, il ne semble pas.

  2. Y a-t-il une garantie que Reader peut réellement read()contenir 1 000 octets?

Cela se produit sur une boîte liée sérieusement aux E / S. Par exemple, saraffiche un temps d'attente d'environ 1 seconde. Dans mon cas, le Reader attend en fait 10 secondes APRÈS avoir reçu l'événement inotify avant d'appeler statet d'obtenir des résultats trop petits.

J'avais espéré que l'événement inotify ne serait pas livré tant que le dossier ne serait pas prêt. Ce que je soupçonne réellement, c'est que l'événement inotify se déclenche PENDANT l' write()appel dans le Writer, et les données sont réellement disponibles pour d'autres processus sur le système chaque fois qu'il se trouve être prêt. Dans ce cas, 10s n'est pas suffisant.

Je suppose que je cherche juste à confirmer que le noyau implémente réellement la façon dont je devine. De plus, s'il existe des options, éventuellement, pour modifier ce comportement?

Enfin, quel est le point d'inotifier, compte tenu de ce comportement? Vous êtes de toute façon réduit à interroger le fichier / répertoire, après avoir reçu l'événement, jusqu'à ce que les données soient réellement disponibles. Autant le faire tout le temps, et oublier l'inotification.

*** ÉDITER ** * * D'accord, comme cela arrive souvent, le comportement que je vois a du sens, maintenant que je comprends vraiment ce que je fais. ^ _ ^

Je répond en fait à un événement IN_CREATE sur le répertoire dans lequel se trouve le fichier. Je suis donc en train de stat () le fichier en réponse à la création du fichier, pas nécessairement l'événement IN_MODIFY, qui peut arriver plus tard.

Je vais changer mon code pour que, une fois que j'obtiens l'événement IN_CREATE, je m'abonne à IN_MODIFY sur le fichier lui-même, et je n'essaierai pas réellement de lire le fichier jusqu'à ce que j'obtienne l'événement IN_MODIFY. Je me rends compte qu'il y a une petite fenêtre dans laquelle je peux manquer une écriture dans le fichier, mais cela est acceptable pour mon application, car dans le pire des cas, le fichier sera fermé après un nombre maximum de secondes.

Todd Freed
la source
Vous pouvez utiliser un canal au lieu d'un fichier. Voir homme mknod
daniel kullmann
Nous devons utiliser un fichier standard afin d'avoir un tampon de plusieurs téraoctets entre les deux processus. Également pour conserver les données dans le tampon lors du redémarrage.
Todd a libéré le

Réponses:

5

D'après ce que je vois dans la source du noyau , inotify ne se déclenche qu'une fois l'écriture terminée (c'est-à-dire que votre supposition est fausse). Une fois la notification déclenchée, seules deux autres choses se produisent dans sys_writela fonction qui implémente l' writeappel système: définir certains paramètres du planificateur et mettre à jour la position sur le descripteur de fichier. Ce code est similaire depuis 2.6.14 . Au moment où la notification se déclenche, le fichier a déjà sa nouvelle taille.

Vérifiez les choses qui peuvent mal tourner:

  • Peut-être que le lecteur reçoit d'anciennes notifications, de l'écriture précédente.
  • Si le lecteur appelle stat, puis appelle readou vice versa, quelque chose peut se produire entre les deux. Si vous continuez à ajouter au fichier, appeler en statpremier garantit que vous pourrez lire jusque-là, mais il est possible que davantage de données aient été écrites au moment où le lecteur appelle read, même s'il n'a pas encore reçu la notification inotify.
  • Ce writen'est pas parce que l'écrivain appelle que le noyau écrira le nombre de caractères demandé. Il y a très peu de circonstances où les écritures atomiques sont garanties jusqu'à n'importe quelle taille. writeCependant, chaque appel est garanti atomique: à un moment donné, les données ne sont pas encore écrites, puis soudainement n octets ont été écrits, où n est la valeur de retour de l' writeappel. Si vous observez un fichier partiellement écrit, cela signifie qu'il a writeretourné moins que son argument de taille.

Les outils utiles pour enquêter sur ce qui se passe incluent:

  • strace -tt
  • le sous-système auditd
Gilles 'SO- arrête d'être méchant'
la source
Merci pour les idées. Je viens de passer en revue le code, et je ne vérifie en fait que -1 comme valeur de retour d'écriture pour le cas d'erreur. Ainsi, il se peut que je n'obtienne pas la valeur de retour d'écriture indiquant que toutes les données ont été écrites. Néanmoins, quand je regarde le fichier après coup, je sais que tous les "1000" octets ont en fait été écrits, car le fichier est en bon état, c'est-à-dire qu'il est constitué d'enregistrements entiers et cohérents. Le premier enregistrement n'est donc pas en partie écrit.
Todd a libéré le