Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

inotify sur un repertoire: le champs inotify_event.len semble rester=0 pour un repertoire

82 réponses
Avatar
Zeyes
J'ai poste ca aussi sur fr.comp.os.linux.debats parceque ca bouge pas
mal la-bas..
;-)

Bonour,
j"ai regarde
http://www.linuxjournal.com/node/8478/print
Extrait:
"
The name field contains the name of the object to which the event
occurred, relative to wd, if applicable. For example, if a watch for
writes in /etc triggers an event on the writing to /etc/vimrc, the name
field will contain vimrc, and the wd field will link back to the /etc watch
"
Mais ca marche pas chez moi: le champs inotify_event.len reste a 0,
alors qu'il semble rester des octets a lire...
quelqu'un a une idee?
Est-ce normal? Pas encore implemente?
Merci

10 réponses

Avatar
Zeyes
Zeyes :

Et ca n'arrete plus de boucler (comme s'il y a vait encore des octetes)
plein de

coucou
lg nom: 0

Strange, non?


Ça sent le read qui ne renvoie rien. Lance ton a.out via

strace -o /tmp/blah ./a.out tata "echo coucou"

, et regarde dans le fichier /tmp/blah, tu as la trace des appels systèmes
effectués.
Bonjour... je me suis repenche un peu sur le truc:

donc en fait (hormis les bugs), le pb est que read ne lit rien si je ne
demande pas de lire tout... currieux, j'aurais pense qu'on pouvait lire
par morceau. Dans mon exemple y'a 32 bytes dans mon fd de inotify, si
j'en lis moins, read me retourne 0

J'aurais aime lire le .name separement, mais comme ca, pas possible!


Avatar
Luc.Habert.00__arjf
Zeyes :

donc en fait (hormis les bugs), le pb est que read ne lit rien si je ne
demande pas de lire tout... currieux, j'aurais pense qu'on pouvait lire
par morceau. Dans mon exemple y'a 32 bytes dans mon fd de inotify, si
j'en lis moins, read me retourne 0


OK, ça se tient. Pfiou, ils pourraient pas le dire dans la page de man?

J'aurais aime lire le .name separement, mais comme ca, pas possible!


Ça doit pas mal simplifier l'implémentation du côté du noyau : ça leur
permet de juste maintenir une liste d'évènements, et non pas un buffer avec
des bouts d'évènements marshallés.

Avatar
Zeyes
La struct inotify_event est définie ainsi (je prend la définition du .h
plutôt que celle de la page de man, car elle n'est pas syntaxiquement
correcte) :

struct inotify_event {
__s32 wd; /* watch descriptor */
__u32 mask; /* watch mask */
__u32 cookie; /* cookie to synchronize two events*/
__u32 len; /* length (including nulls) of name*/
char name[0]; /* stub for possible name */
};

son sizeof vaut la distance entre son début et le début du champ name. Donc
il ne faut pas faire le « nom[0]=notification.name[0] », et faire un read de
tout le nom dans nom.
oui tres juste... oh j'avais pris l'apero.... ;-)


__int32_t longueur_nom;



Pourquoi pas int? Si tu veux pinailler, c'est « size_t », le bon type
Je sais plus... mais tu as raison.



observation = inotify_add_watch (notificateur , nom_de_fichier_a_surveiller, IN_MODIFY);



Il conviendrait de tester si ça a réussi.
Je n'ai pas trouve qelle valeur de retour signale une erreur


[...]

Quand tu fais un read, rien ne te garantie que le noyau va vraiment te lire
autant d'octets d'un coup que tu lui en demande. Il faut faire une boucle
qui compare la valeur de retour à la taille demandée.
[...]

Bon, maintenant je ne pense pas que tout ça ait quoi que ce soit à voir avec
ton problème.


Ben en fait, si :-( ..... mais boucler quand read renvoie 0, ca me
semble zarbi.. mais bon, je vais essayer....



Avatar
Luc.Habert.00__arjf
Zeyes :

observation = inotify_add_watch (notificateur , nom_de_fichier_a_surveiller, IN_MODIFY);



Il conviendrait de tester si ça a réussi.
Je n'ai pas trouve qelle valeur de retour signale une erreur



man inotify_add_watch

->

RETURN VALUE
On success, inotify_add_watch() returns a non-negative watch
descriptor. On error -1 is returned and errno is set appropriately.


Ben en fait, si :-( ..... mais boucler quand read renvoie 0, ca me
semble zarbi.. mais bon, je vais essayer....


En fait, avec un fd pointant vers un truc non mutant (fichier, pipe,
socket), read ne renvoie 0 que quand on est au bout du truc (bout du
fichier, ou canal de communication fermé), donc il ne faut pas boucler
dessus. C'est sur une lecture partielle (résultat de read strictement
positive mais strictement inférieur à la taille demandée) qu'il faut
boucler.

Là, il se trouve qu'on communique directement avec un sblurb dans le noyau
qui répond comme il l'amuse aux requêtes qu'on lui fait, il faut donc
adopter des mesures particulières (et tu as trouvé tout seul quoi faire).




Avatar
Zeyes
Zeyes :

donc en fait (hormis les bugs), le pb est que read ne lit rien si je ne
demande pas de lire tout... currieux, j'aurais pense qu'on pouvait lire
par morceau. Dans mon exemple y'a 32 bytes dans mon fd de inotify, si
j'en lis moins, read me retourne 0


OK, ça se tient. Pfiou, ils pourraient pas le dire dans la page de man?

J'aurais aime lire le .name separement, mais comme ca, pas possible!


Ça doit pas mal simplifier l'implémentation du côté du noyau : ça leur
permet de juste maintenir une liste d'évènements, et non pas un buffer avec
des bouts d'évènements marshallés.
En insitant.... le read renvoit toujours 0...

Bon, il faut que j'alloue un maousse buffer, ou tu vois plus subtil?


Avatar
Luc.Habert.00__arjf
Zeyes :

Bon, il faut que j'alloue un maousse buffer, ou tu vois plus subtil?


Comme l'indique la page de man de inotify :

The FIONREAD ioctl() returns the number of bytes available to read
from an inotify file descriptor.

. Donc tu utilises cet ioctl pour savoir quelle est la taille du buffer
nécessaire, tu l'alloue, et tu reade d'autant. Attention, ça peut, a priori,
te renvoyer plusieurs évènements d'un coup.

Avatar
Zeyes

man inotify_add_watch

->

RETURN VALUE
On success, inotify_add_watch() returns a non-negative watch
descriptor. On error -1 is returned and errno is set appropriately.


Merci, j'ai trouve ca sur gargle, parce que je ne l'ai pas ici.

Ben en fait, si :-( ..... mais boucler quand read renvoie 0, ca me
semble zarbi.. mais bon, je vais essayer....


En fait, avec un fd pointant vers un truc non mutant (fichier, pipe,
socket), read ne renvoie 0 que quand on est au bout du truc (bout du
fichier, ou canal de communication fermé), donc il ne faut pas boucler
dessus. C'est sur une lecture partielle (résultat de read strictement
positive mais strictement inférieur à la taille demandée) qu'il faut
boucler.

Là, il se trouve qu'on communique directement avec un sblurb dans le noyau
qui répond comme il l'amuse aux requêtes qu'on lui fait, il faut donc
adopter des mesures particulières (et tu as trouvé tout seul quoi faire).


J'ai de la doc (en local, inotify.txt) et y'a ca dedans:
"
You can find the size of the current event queue via the standard FIONREAD
ioctl on the fd returned by inotify_init().
"
je trouve pas FIONREAD dans mes .h
Bon gargle
Mais ca serait plus propre d'allouer juste la taille necessaire...
meme si finalement un second evenement arrive pendant ce temps, je le
lirai au prochain coup...
T'en penses quoi?
Merci de ton aide


Avatar
Zeyes
Zeyes :

Bon, il faut que j'alloue un maousse buffer, ou tu vois plus subtil?


Comme l'indique la page de man de inotify :

The FIONREAD ioctl() returns the number of bytes available to read
from an inotify file descriptor.

. Donc tu utilises cet ioctl pour savoir quelle est la taille du buffer
nécessaire, tu l'alloue, et tu reade d'autant. Attention, ça peut, a priori,
te renvoyer plusieurs évènements d'un coup.
Merci....

J'avais finalement vu.
Bon ca marche,
cr=ioctl(notificateur, FIONREAD, &ln)
Met bien 32 dans ln
Tu penses que je peux utiliser realloc() pour gagner du temps?
C'est politiquement correct?


Avatar
Luc.Habert.00__arjf
Zeyes :

Tu penses que je peux utiliser realloc() pour gagner du temps?
C'est politiquement correct?


Bah oui...

Autre solution : utiliser un tableau dynamique. Attention à ne pas le
définir comme un tableau de char, car il ne sera pas forcément bien aligné
pour contenir un struct inotify_event à sa première case. Je ne vois pas
comment faire autrement qu'un tableau de struct inotify_event, de taille
« ln/sizeof(struct inotify_event)+1 ».

Avatar
Nicolas George
Luc Habert wrote in message <f0058u$16q2$:
Je ne vois pas
comment faire autrement qu'un tableau de struct inotify_event, de taille
« ln/sizeof(struct inotify_event)+1 ».


union {
struct inotify_event;
char dummy[ln];
}