OVH Cloud OVH Cloud

Garder les messages les plus récents dans une message queue

7 réponses
Avatar
rmoyen
Salut,

Un poil de contexte pour expliquer ce que je veux faire et qui me pose
probl=E8me :
J'ai un programme qui tourne (longtemps...) et je veux avoir un
deuxi=E8me programme, diff=E9rent, qui puisse surveiller o=F9 en est le
premier. Pour =E9changer des infos entre ces deux processus totalement
s=E9par=E9s, j'utilise une message queue (comme le deuxi=E8me programme
peut ne pas exister, il me semble que j'aurais du mal =E0 faire ce que
je veux avec un pipe, par exemple).

=C7a marche globalement tr=E8s bien, mon premier programme (cr=E9e et)
remplit (et d=E9truit) la queue, mon deuxi=E8me se connecte dessus et lit
les messages, parfait.

Mais comme le deuxi=E8me programme n'existe pas forc=E9ment, pour =E9viter
que le premier ne bloque quand la queue est pleine, j'=E9cris dans la
queue avec msgsnd(..., IPC_NOWAIT). Du coup, quand la queue est pleine
(si personne ne lit, donc), les derniers messages sont abandonn=E9s et
le programme continue sans perdre de temps.

Le probl=E8me, c'est si le programme surveillant est lanc=E9 alors que le
premier programme tourne depuis un moment : il va se brancher sur le
queue et lire les messages, mais il aura les premiers messages, puis un
grand vide (tous les messages qui ont =E9t=E9 abandonn=E9s parce que la
queue =E9tait pleine), puis les derniers messages (ceux post=E9s depuis
qu'il a commenc=E9 =E0 lire dans la queue). Par exemple, si la queue
contient 5 messages maxi, il aura les messages 1, 2, 3, 4, 5, puis [le
2=E8me prog commence =E0 vider la queue =E0 cet instant] 42, 43, 44, ...

Pour finir, ma question est : existe-t-il un moyen simple de faire en
sorte que, lorsque la queue est pleine, ce soit non pas les messages
les plus r=E9cents, mais les messages les plus anciens, qui soient
abandonn=E9s ? De telle sorte que dans l'exemple pr=E9c=E9dent, le
deuxi=E8me programme lise 37, 38, 39, 40, 41 [d=E9but du 2=E8me prog] 42,
43... ?

J'entrevois vaguement une solution avec une partie du 1er programme
lisant la queue en permanence et s'occuppant de faire le m=E9nage
correctement (peut-=EAtre avec une deuxi=E8me queue), mais =E7a me semble
horriblement compliqu=E9.

Merci d'avance !
--=20
R=E9mi Moyen

7 réponses

Avatar
Nicolas George
wrote in message
:
J'entrevois vaguement une solution avec une partie du 1er programme
lisant la queue en permanence et s'occuppant de faire le ménage
correctement (peut-être avec une deuxième queue), mais ça me semble
horriblement compliqué.


On peut faire ça en beaucoup plus simple : si msgsend renvoie EAGAIN,
signalant que la queue est pleine, lire un message pour faire de la place.

D'ailleurs, tu dois pouvoir faire la même chose avec un FIFO.

Avatar
rmoyen
Nicolas George wrote:

J'entrevois vaguement une solution avec une partie du 1er programme
lisant la queue en permanence et s'occuppant de faire le ménage
correctement (peut-être avec une deuxième queue), mais ça me semb le
horriblement compliqué.


On peut faire ça en beaucoup plus simple : si msgsend renvoie EAGAIN,
signalant que la queue est pleine, lire un message pour faire de la place.


Ah oui, bien sûr ! C'est en effet tout simple à implémenter, ça, et
y'a pas de raisons que ça ne marche pas.

D'ailleurs, tu dois pouvoir faire la même chose avec un FIFO.


Ben, si j'ai bien compris ce que j'ai lu (j'avoue sans honte que, même
si ça faisait longtemps que j'en entendais praler, j'ai commencé à
regarder de près toutes ces méthodes de communication il y a quelques
jours seulement), un processus qui écrit dans une FIFO bloque si il
n'y a personne qui lit à l'autre bout, non ?

Dans mon cas, le processus "lecteur" peut exister ou pas, le premier
processus n'en sait rien. Et pire encore, le lecteur doit pouvoir
exister à un moment, puis disparaître, puis être relancé, etc. Il
me semble qu'il n'y a guère que les messages queue qui me permettent
de faire ça ?

En tout cas, merci pour ta suggestion !
--
Rémi Moyen


Avatar
Thierry Boudet
On 2006-10-27, wrote:

Dans mon cas, le processus "lecteur" peut exister ou pas, le premier
processus n'en sait rien. Et pire encore, le lecteur doit pouvoir
exister à un moment, puis disparaître, puis être relancé, etc. Il
me semble qu'il n'y a guère que les messages queue qui me permettent
de faire ça ?

J'ai pas tout suivi, mais il me semble qu'un process qui reçoit

ces divers messages et gère un buffer circulaire en shared mem
pourrait être une solution...


--
La photo argentique n'est pas morte ? elle existe en 64 bits ?
;-) Depuis que le 25 bits est mort et enterré...


Avatar
lhabert
:

un processus qui écrit dans une FIFO bloque si il n'y a personne qui lit à
l'autre bout, non ?


Tu peux le passer en mode non-bloquant avec fcntl. En fait, tu veux
directement l'ouvrir en mode non-bloquant (O_NONBLOCK), histoire de ne pas
bloquer sur le open.

Avatar
rmoyen
Luc Habert wrote:

un processus qui écrit dans une FIFO bloque si il n'y a personne qui lit à
l'autre bout, non ?


Tu peux le passer en mode non-bloquant avec fcntl. En fait, tu veux
directement l'ouvrir en mode non-bloquant (O_NONBLOCK), histoire de ne pas
bloquer sur le open.


Ah oui, j'avais raté ça dans le man. Bon, ceci dit, maintenant que
j'ai tout implémenté avec des message queue (et que ça a l'air de
tout marcher), à moins que je ne tombe sur une très grosse raison de
changer d'implémentation, je vais m'en tenir là.

D'autant plus que la notion de communication par petits messages,
chacun d'un type précis, me semble plus adaptée à ce que je veux
échanger entre les processus qu'un flux d'infos plus ou moins continu
(type FIFO) -- même si je pourrais évidemment m'en accomoder aussi,
si il fallait.

Merci quand même !
--
Rémi Moyen


Avatar
Nicolas George
wrote in message
:
Ben, si j'ai bien compris ce que j'ai lu (j'avoue sans honte que, même
si ça faisait longtemps que j'en entendais praler, j'ai commencé à
regarder de près toutes ces méthodes de communication il y a quelques
jours seulement), un processus qui écrit dans une FIFO bloque si il
n'y a personne qui lit à l'autre bout, non ?


Ce n'est pas exactement ça. D'une part, tu vas bloquer à l'ouverture du FIFO
s'il n'y a pas de lecteur, mais tu peux éviter ça soit en ouvrant en
non-bloquant, soit en ouvrant en lecture-écriture. Si tu comptes appliquer
la politique de lire quand il n'y a plus de place, alors cette dernière
solution convient très bien.

D'autre part, si tu tentes d'écrire alors qu'il n'y a pas de lecteur, tu vas
te prendre un SIGPIPE. Mais là encore, si tu as ouvert en lecture-écriture,
ce n'est pas un problème.

Enfin, si tu tentes d'écrire alors qu'aucun lecteur ne lit effectivement, tu
vas te retrouver bloqué, mais ça s'évite en mettant en non-bloquant. Et
surtout, tu as la garantie d'avoir un buffer d'au moins PIPE_BUF, qui vaut
au moins 512.

La difficulté avec cette méthode, c'est l'atomicité des lectures : si tu as
deux processus qui lisent en même temps (typiquement, l'écriveur qui veut
faire de la place, et le vrai lecteur qui vient d'être lancé), et des
messages qui font plus d'un octet, tu n'as aucune garantie que le découpage
des lectures tombe sur des limites de messages. Ça peut se corriger avec un
verrou. Sous certains Unix, on peut verrouiller un pipe, je ne sais pas à
quel point c'est standard.

Concernant l'intérêt d'utiliser un pipe plutôt qu'une file de messages :
j'ai toujours trouvé que l'API des IPC SysV était vraiment très mal conçue,
et très mal intégrée au système Unix. Un pipe, au moins, peut être
multiplexé avec select ou poll, passé sur un file descriptor, etc.

Avatar
rmoyen
Nicolas George wrote:

[snip explications sur les FIFOs]

Je crois que je comprends ce que tu veux dire, je n'avais pas fouillé
cette piste en détail.

La difficulté avec cette méthode, c'est l'atomicité des lectures
[snip]


Ah oui, en effet...

Concernant l'intérêt d'utiliser un pipe plutôt qu'une file de messa ges :
j'ai toujours trouvé que l'API des IPC SysV était vraiment très mal conçue,
et très mal intégrée au système Unix. Un pipe, au moins, peut ê tre
multiplexé avec select ou poll, passé sur un file descriptor, etc.


Euh... je suis un peu perdu, là. J'ai jamais utilisé (ni regardé de
près !) select/poll...

Enfin, dans les limites de ce dont j'ai besoin, ça ne me semble pas
vraiment génant. Et, comme je le disais ailleurs, j'ai le sentiment
qu'une queue a une structure plus adaptée au type d'infos que je veux
tranférer (des messages et non pas un flux plus ou moins continu).

Merci pour tes explications !
--
Rémi Moyen