Utiliser read avec inotify

J’ai étudié l’appel inotify, mais je suis toujours un peu floconneux en ce qui concerne l’interface de lecture. Voici les ressources les plus pertinentes que j’ai pu trouver sur la manière de s’interfacer correctement avec inotify en utilisant read (2):

  • http://www.ibm.com/developerworks/linux/library/l-ubuntu-inotify/index.html
  • http://www.linuxjournal.com/article/8478

Ils l’implémentent tous les deux de la même manière, ils définissent d’abord les tailles suivantes:

#define EVENT_SIZE ( sizeof (struct inotify_event) ) #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) 

Et puis ils les utilisent de cette manière:

 length = read( fd, buffer, BUF_LEN ); if ( length < 0 ) { perror( "read" ); } while ( i len; } 

Maintenant, nous soaps que name fait partie de struct inotify_event et qu’il a une longueur variable. Donc, le dernier inotify_event dans le tampon ne peut-il pas être tronqué?

Supposons qu’il y ait 1023 inotify_events avec un chemin de 16 octets et un autre avec un chemin de 32 octets. Qu’est-ce qui va arriver ensuite? Le plus tard tronqué? Ou le kernel verra-t-il qu’il ne rentrera pas dans la mémoire tampon et laissera tout cela complètement?

Utilisation de base

Selon inotify (7) , vous pouvez utiliser l’ioctl FIONREAD pour connaître la quantité de données pouvant être lue et pour dimensionner votre tampon en conséquence. Voici un code (très approximatif) qui peut accomplir cela:

 unsigned int avail; ioctl(inotify_fd, FIONREAD, &avail); char buffer[avail]; read(fd, buffer, avail); int offset = 0; while (offset < avail) { struct inotify_event *event = (inotify_event*)(buffer + offset); // Insert logic here my_process_inotify_event(event); offset = offset + sizeof(inotify_event) + event->len; } 

Utilisation plus robuste

inotify-tools fournit une interface de niveau supérieur pour inotify. Vous pouvez l’utiliser au lieu d’accéder à inotify, ou vous pouvez voir comment il implémente inotifytools_next_events pour lire en toute sécurité et de manière robuste tous les événements disponibles.

Événements partiels et troncature

En réponse à vos questions sur la troncature, je ne pense pas que le kernel renvoie jamais un événement inotify_event partiel ni ne tronque un inotify_event si le tampon donné est trop petit pour tous les événements. Le paragraphe suivant de la page de manuel inotify (7) suggère ceci:

Le comportement lorsque le tampon donné à read (2) est trop petit pour renvoyer des informations sur l’événement suivant dépend de la version du kernel: dans les kernelx antérieurs à 2.6.21, read (2) renvoie 0; depuis le kernel 2.6.21, read (2) échoue avec l’erreur EINVAL.

De même que les commentaires suivants de inotifytools.c :

 // oh... no. this can't be happening. An incomplete event. // Copy what we currently have into first element, call self to // read remainder. // oh, and they BETTER NOT overlap. // Boy I hope this code works. // But I think this can never happen due to how inotify is written.