[C] POSIX message queues : #define MQ_MAXMSG 10 ???

POSIX message queues : #define MQ_MAXMSG 10 ??? [C] - C - Programmation

Marsh Posté le 26-11-2008 à 17:32:52    

Bonjour à tous,
 
J'ai écrit un bout de code dans mon appli en utilisant les messages queues fournies par la lib real time (librt) du système sous linux, je teste le bouzin et ça ne marche pas. Je tâtonne, je cherche un peu sur le net, et finalement je découvre que l'API n'autorise l'utilisation que de 10 messages par queue...
 

Code :
  1. #define MQ_MAXMSG  10


 :o  
 
La structure mq_attr permet de définir mq_maxmsg le nombre de message de la queue, si par malheur on en définit plus de 10 mq_open échoue avec un "invalid argument"...
 
Le #define MQ_MAXMSG n'est documenté nulle part, ce n'est qu'en cherchant sur le net que j'ai trouvé d'autres personnes qui ont rencontré le problème. Le plus étonnant c'est qu'on trouve sur le net d'autres version de la lib qui définissent MQ_MAXMSG à 40, ou à 100. Pourquoi cela n'est-il pas normalisé? Pour ma part mon système possède la librt-2.3.4.so, mais mon appli doit fonctionner sur d'autres machines. Je vais partir sur une autre solution mais j'aurais aimé comprendre cette aberration de fixer un paramètre aussi important dans une lib aussi commune...


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 26-11-2008 à 17:32:52   

Reply

Marsh Posté le 27-11-2008 à 10:22:48    

up :)


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 10:52:26    

Attention, ça ne marche que mq_open de changer mq_maxmsg.

Reply

Marsh Posté le 27-11-2008 à 10:56:48    

kaloskagatos a écrit :


Le #define MQ_MAXMSG n'est documenté nulle part, ce n'est qu'en cherchant sur le net que j'ai trouvé d'autres personnes qui ont rencontré le problème. Le plus étonnant c'est qu'on trouve sur le net d'autres version de la lib qui définissent MQ_MAXMSG à 40, ou à 100. Pourquoi cela n'est-il pas normalisé?

Parce que c'est une valeur par défaut sans grande importance ? Si tu veux plus, demande plus.
 
T'as tout dans le man, y compris le sysctl /proc pour avoir une valeur supérieure à 10.

Reply

Marsh Posté le 27-11-2008 à 11:06:58    

Taz a écrit :

Attention, ça ne marche que mq_open de changer mq_maxmsg.


 
Je comprends pas la phrase :D mq_open plante avec invalid argument :
 

Code :
  1. struct mq_attr atr;
  2. atr.mq_maxmsg = 11;
  3. atr.mq_msgsize = 1024;
  4. mq_open("/dawa", O_CREAT | O_RDWR , S_IRWXO, &atr);


 
 

Taz a écrit :

Parce que c'est une valeur par défaut sans grande importance ? Si tu veux plus, demande plus.
 
T'as tout dans le man, y compris le sysctl /proc pour avoir une valeur supérieure à 10.


 
 
Ok je check baby


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:09:57    

Je sais que t'as raison, laisse moi chercher.

 


Mais en fait ça me fait chier si je dois régler le nombre max de messages depuis le système, en root à tous les coups, c'est pas très user compliant :/ Comment je fais si je veux distribuer mon appli et être sûr que ça plantera pas à l'exécution?

 

Patapay je cherche toujours le sysctl /proc


Message édité par kaloskagatos le 27-11-2008 à 11:12:16

---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:18:33    

minable ta non-initialisation de struct ... soit fais un memset, soit fais un simple "attr = { 0, 1, 2, 3 };" pour être sur que tous les membres que tu n'initilises pas sont à 0 plutôt qu'à des valeurs délirantes.
 
Si t'as besoin d'une taille plus grande:
- tu peux la vérifier en lisant /proc ou quand tu crées ta file, tu vois bien si ton open marche avec la valeur que tu demandes ou pas
- quand la file est pleine, ça bloque, à moins que tu mettes un flag pour que ça ne bloque pas, auquel cas, tu peux ressayer plus tard.

Reply

Marsh Posté le 27-11-2008 à 11:19:49    

>>T'as tout dans le man, y compris le sysctl /proc pour avoir une valeur supérieure à 10.  
 
ok bon ça j'ai pas trouvé où tu l'avais vu dans le man de mq_
 
 
sysctl on peut le faire depuis le code, mais bon toucher au noyau c'est pas très à propos dans mon appli, je pense que j'avais fait fausse route en utilisant ça.


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:23:15    

Taz a écrit :

minable ta non-initialisation de struct ... soit fais un memset, soit fais un simple "attr = { 0, 1, 2, 3 };" pour être sur que tous les membres que tu n'initilises pas sont à 0 plutôt qu'à des valeurs délirantes.

 


 

C'est toi t'es minable [:masklinn]

 
Taz a écrit :

 

Si t'as besoin d'une taille plus grande:
- tu peux la vérifier en lisant /proc ou quand tu crées ta file, tu vois bien si ton open marche avec la valeur que tu demandes ou pas
- quand la file est pleine, ça bloque, à moins que tu mettes un flag pour que ça ne bloque pas, auquel cas, tu peux ressayer plus tard.

 

- Je veux pas vérifier si ma valeur >10 que je demande marche, je veux que ça marche avec 100 messages par file
- HS

 


Mais merci pour ton intervention, j'y vois plus clair, et je me sens un peu plus crétin :jap:


Message édité par kaloskagatos le 27-11-2008 à 11:23:57

---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:28:48    

Nan mais je pense que ton erreur, c'est juste un bug de données pas initialisée ...
 
10 ou 100, c'est le même problème, si tu ne gères pas le cas où la file est pleine, ça fera tot ou tard des surprises. C'est dans le manuel, 100 ça ne marchera pas avec les valeurs par défaut système. La taille totale de la file faut pas l'oublier non plus.

Reply

Marsh Posté le 27-11-2008 à 11:28:48   

Reply

Marsh Posté le 27-11-2008 à 11:34:43    

Je vois pas de bug dans mon initialisation :
 

Code :
  1. struct mq_attr {
  2.     long mq_flags;       /* Flags: 0 or O_NONBLOCK */
  3.     long mq_maxmsg;      /* Max. # of messages on queue */
  4.     long mq_msgsize;     /* Max. message size (bytes) */
  5.     long mq_curmsgs;     /* # of messages currently in queue */
  6. };


 
mq_flags ça va changer quelque chose au moment d'envoyer/lire des messages, moi ça plante quand je fais un mq_open avec mq_maxmsg = 11.
 
mq_curmsgs faut pas l'initialiser si je ne m'abuse.
 
Je poste mon de code de test


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:40:45    

Code :
  1. # struct mq_attr atr;
  2. atr.mq_maxmsg = 11;
  3. atr.mq_msgsize = 1024;


 
Et les autres membres, ils valent quoi ? UB.

Reply

Marsh Posté le 27-11-2008 à 11:41:35    

avec #define MAXMSG   11 ça plante avec "Ca plante à l'ouverture: Invalid argument"
avec 10 ça passe.
Mon code est beau.

 

gcc -Wall -pedantic -ansi -lrt mqueue.c

 
Code :
  1. #include <mqueue.h>
  2. #include <sys/stat.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #define MAXMSG   11 /* Nombre maximal de message dans la file */
  6. #define MSGSIZE 256 /* Taille maximale des messages */
  7. #define QNAME "/dawa" /* nom de la file */
  8. #define NBSEND    10 /* Nombre de messages effectifs */
  9. #define SUPERGRAND 1000000 /* taille de buffer */
  10. /* -------------------------------------------------------------------------- */
  11. /* Creation de la queue */
  12. /* -------------------------------------------------------------------------- */
  13. mqd_t init()
  14. {
  15.    struct mq_attr   mqattr ;
  16.    mqd_t            qid    ;
  17.    /* Parametre de l'ouverture de la file */
  18.    mqattr.mq_flags   = 0;
  19.    mqattr.mq_maxmsg  = MAXMSG ;
  20.    mqattr.mq_msgsize = MSGSIZE ;
  21.    mqattr.mq_curmsgs = 0;
  22.    /* Suppression d'une eventuelle queue */
  23.    if( mq_unlink( QNAME ) == 0 )
  24.       printf( "Warning : La file %s a été supprimée.\n", QNAME ) ;
  25.    /* Creation de la file */
  26.    qid = mq_open( QNAME, O_RDWR | O_CREAT | O_NONBLOCK , S_IRWXO, &mqattr ) ;
  27.    if( qid == (mqd_t) -1 )
  28.       perror( "Ca plante à l'ouverture" ) ;
  29.    return qid ;
  30. }
  31. /* -------------------------------------------------------------------------- */
  32. /* Suppression de la queue */
  33. /* -------------------------------------------------------------------------- */
  34. int close( mqd_t qid )
  35. {
  36.    /* Abandon du descripteur */
  37.    if( mq_close( qid ) )
  38.    {
  39.       perror( "Ca plante à la fermeture, mais c'est pas vrai !" ) ;
  40.       return 1 ;
  41.    }
  42.    /* Suppression effective de la queue */
  43.    if( mq_unlink( QNAME ) )
  44.    {
  45.       perror( "Ca plante à la destruction de la queue" ) ;
  46.       return 1 ;
  47.    }
  48.    return 0 ;
  49. }
  50. /* -------------------------------------------------------------------------- */
  51. /* Envoi */
  52. /* -------------------------------------------------------------------------- */
  53. int send( mqd_t id )
  54. {
  55.    char *msg = "Ceci est un texte toujours plus long que lg" ;
  56.    if( mq_send( id, msg, strlen(msg), 0 ) )
  57.    {
  58.       perror( "Ca plante à l'envoi nondidiou" ) ;
  59.       return 1 ;
  60.    }
  61.    return 0 ;
  62. }
  63. /* -------------------------------------------------------------------------- */
  64. /* Reception */
  65. /* -------------------------------------------------------------------------- */
  66. int receive( mqd_t qid )
  67. {
  68.    char      buffer[SUPERGRAND] ;
  69.    mqd_t     retVal  ;
  70.    /* Reception d'un message */
  71.    retVal = mq_receive( qid, buffer, SUPERGRAND, NULL ) ;
  72.    if( retVal < 1 )
  73.    {
  74.       perror( "Nous avons rencontré un problème sérieux." ) ;
  75.       printf( "ben ouais, on a lu %d octets\n", retVal ) ;
  76.       return 1 ;
  77.    }
  78.    printf( "On a lu %d octets sans problème\n", retVal ) ;
  79.    return 0 ;
  80. }
  81. /* -------------------------------------------------------------------------- */
  82. /* Main ! */
  83. /* -------------------------------------------------------------------------- */
  84. int main( int argc, char **argv )
  85. {
  86.    mqd_t qid ;
  87.    unsigned i ;
  88.    /* Ouverture de la mqueue de m... */
  89.    qid = init() ;
  90.    if( qid == (mqd_t) -1 )
  91.       return 1 ;
  92. printf( "Init Ok. En attente du feu vert go ouais.\n" ) ;
  93. getchar() ;
  94.    /* Envoi effectif */
  95.    for( i=0; i < NBSEND ; ++i )
  96.    {
  97.       if( send( qid ) )
  98.       {
  99.          printf( "La foirage arrive à l'envoi %u\n", i ) ;
  100.          return 1 ;
  101.       }
  102.    }
  103. printf( "Send Ok. En attente du feu vert go ouais.\n" ) ;
  104. getchar() ;
  105.    for( i=0; i < NBSEND ; ++i )
  106.    {
  107.       if( receive( qid ) )
  108.       {
  109.          printf( "La foirage arrive à la récepcheune %u\n", i ) ;
  110.          return 1 ;
  111.       }
  112.    }
  113. printf( "Receive Ok. En attente du feu vert go ouais.\n" ) ;
  114. getchar() ;
  115.    /* Fermeture qui plante ou pas */
  116.    return close( qid ) ;
  117. }


Message édité par kaloskagatos le 27-11-2008 à 11:44:07
Reply

Marsh Posté le 27-11-2008 à 11:42:39    

1) et le flag, il prend quelle valeur ?
2) voir premier message. Il faut augmenter la limite système.

Reply

Marsh Posté le 27-11-2008 à 11:44:06    

'tain t'es chaud de créer ta propre fonction send ... man 2 send

Reply

Marsh Posté le 27-11-2008 à 11:44:30    

J'ai tout initialisé mais sans succès


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:46:08    

Et quand je te parlais de taille de file.
 
 
SUPERGRAND 1000000
 
ça fait du bon bourrage de pile par la suite. Etant donné que la taille des messages/files est bien plus petite que ça

Reply

Marsh Posté le 27-11-2008 à 11:46:26    

Taz a écrit :

1) et le flag, il prend quelle valeur ?
2) voir premier message. Il faut augmenter la limite système.


 
 
1) on s'en fout du flag, il sert pas à l'ouverture mais à l'envoi
2) c'est bien ce que j'avais compris, je veux pas toucher au système donc c'est DMC.


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:47:14    

Et manie le perror/strerror/errno pour pouvoir qualifier les -1 retournés, sinon tu peux pas savoir pourquoi ça ne marche pas.

Reply

Marsh Posté le 27-11-2008 à 11:47:54    

Taz a écrit :

Et quand je te parlais de taille de file.
 
 
SUPERGRAND 1000000
 
ça fait du bon bourrage de pile par la suite. Etant donné que la taille des messages/files est bien plus petite que ça


 
 
On s'en fout aussi, c'était pour mes tests perso, bien évidemment ceci n'est pas le logiciel que je développe professionnellement pour mon employeur.


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:49:45    

1) ok j'avais pas lu. Ca reste pas idiot d'utiliser généralement la syntaxe d'initialisation.
 
Je comprends pas pourquoi tu bloques vraiment sur la taille de la file. Si elle est pleine, bah tu bloques dessus jusqu'à qu'un autre processus la vide.

Reply

Marsh Posté le 27-11-2008 à 11:50:12    

Taz a écrit :

'tain t'es chaud de créer ta propre fonction send ... man 2 send


 
je rêve ou tu me parles de socket là? J'ai pas écrit de fonction send, y'a rien dedans.
 

Taz a écrit :

Et manie le perror/strerror/errno pour pouvoir qualifier les -1 retournés, sinon tu peux pas savoir pourquoi ça ne marche pas.


 
Comme je l'ai dit mon code est magnifique :)


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:50:58    

kaloskagatos a écrit :


 
 
On s'en fout aussi, c'était pour mes tests perso, bien évidemment ceci n'est pas le logiciel que je développe professionnellement pour mon employeur.


Bah on s'en fout oui et non, à force de faire des trucs foireux/baclés pour tester, ça devient dur de savoir si ton test marche ou pas.

Reply

Marsh Posté le 27-11-2008 à 11:51:56    

Taz a écrit :

1) ok j'avais pas lu. Ca reste pas idiot d'utiliser généralement la syntaxe d'initialisation.
 
Je comprends pas pourquoi tu bloques vraiment sur la taille de la file. Si elle est pleine, bah tu bloques dessus jusqu'à qu'un autre processus la vide.


 
 
Parce que je bosse sur un simulateur temps réel qui n'a pas le temps d'attendre que la file se vide. Donc j'en reviens à la conclusion que cette API n'est pas faite pour moi.


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 11:52:59    

kaloskagatos a écrit :


 
je rêve ou tu me parles de socket là? J'ai pas écrit de fonction send, y'a rien dedans.
 

(T'as aussi écrit une close. C'est des mauvaises habitudes à ne pas prendre sinon un jour tu le feras vraiment et tu comprendras jamais pourquoi ça marche pas).

Reply

Marsh Posté le 27-11-2008 à 11:53:30    

kaloskagatos a écrit :

 


Parce que je bosse sur un simulateur temps réel qui n'a pas le temps d'attendre que la file se vide. Donc j'en reviens à la conclusion que cette API n'est pas faite pour moi.


Bah t'as le flag d'open et le flag de receives/send qui te permet de ne pas attendre

Message cité 1 fois
Message édité par Taz le 27-11-2008 à 11:53:45
Reply

Marsh Posté le 27-11-2008 à 11:56:08    

Taz a écrit :

(T'as aussi écrit une close. C'est des mauvaises habitudes à ne pas prendre sinon un jour tu le feras vraiment et tu comprendras jamais pourquoi ça marche pas).


 
J'ai pas compris, qu'est-ce que j'ai fait ?  
 
 

Taz a écrit :


Bah t'as le flag d'open et le flag de receives/send qui te permet de ne pas attendre


 
Oui mais ne pas attendre signifie que le send échoue et qu'il faut revenir poster les messages qui ne sont pas passés, moi j'aimerais poster tous mes messages pis continuer à faire autre chose quoi.


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 12:09:02    

Je comprends, mais si tu penses comme ça, tu vas avoir le problème tous les appels systèmes et fonctions qui se sont pas async (à commencer par le moindre read ou write).
 
Soit tu gères dans une boucle le fait que la file soit pleine, soit tu le traites dans un autre thread ou dans un sous-programme chargé de poster.
 
C'est sans fin comme problème.
 
Empiler encore et encore côté envoyeur, ça ne résout pas forcément ton problème puisque y a forcément une limite à un moment et c'est un peu inquiétant que ça ne vide pas au bon rythme en face ?
 
 
C'est du producteur/consommateur de base en IPC: mq, pipe ou autre le système est pas là pour stocker tous tes messages. Il te donne de tuyaux de taille fixe, si tu veux bufferiser plus, il faut que tu le fasses toi même côté utilisateur.

Reply

Marsh Posté le 27-11-2008 à 12:22:46    

J'ai compris ce que tu m'expliques, mais dans mon cas le nombre de messages envoyés a une limite max, c'est dans la spec.  
 
De plus je ne suis pas rentré dans le détail dans mon post mais pour le moment je n'ai qu'un seul processus, l'envoi se fait à t0 et la réception se fait à t1 dans un callback appelé par un échéancier. En bref je me suis fourvoyé avec cette lib, je vais utiliser un buffer circulaire et pis ça ira tout seul.


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 12:30:23    

Ca c'est sur que si c'est pas threadé ni multiprocessé, c'est pas bien la peine de sortir faire de l'IPC. Si ça se trouve, t'as peut-être meme pas besoin de synchronisation.
 
Comme tu dis, un pauvre buffer, de la synchro comme il faut, et ça doit se faire tout seul. Réfléchi bien à la synchro si c'est 2 thread qui communiquent pour faire quelque chose d'intelligent

Reply

Marsh Posté le 27-11-2008 à 12:40:19    

Bein c'est parce que potentiellement un jour ce sera multithreadé que j'ai utilisé ça, donc je voulais déjà le valider.
 
Bon bein thx


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 27-11-2008 à 12:45:07    

kaloskagatos a écrit :

Bein c'est parce que potentiellement un jour ce sera multithreadé que j'ai utilisé ça, donc je voulais déjà le valider.
 
Bon bein thx


c'est pour de la comme entre processus ça.

Reply

Marsh Posté le 27-11-2008 à 15:11:52    

c'est ce que je voulais dire


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 28-11-2008 à 10:33:36    

Taz a écrit :

Code :
  1. # struct mq_attr atr;
  2. atr.mq_maxmsg = 11;
  3. atr.mq_msgsize = 1024;


 
Et les autres membres, ils valent quoi ? UB.


 
 
Au fait ça veut dire quoi UB? Tu m'as insulté?  :fou:


---------------
« Le hasard, c’est différent de la chance. Parce que la chance, je n'en ai jamais. »
Reply

Marsh Posté le 28-11-2008 à 10:35:04    

Tu te fous de la gueule de mon pote?

Reply

Marsh Posté le 28-11-2008 à 11:05:43    

babarpapa a écrit :

Tu te fous de la gueule de mon pote?


suce moi papa!

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed