IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Select et list/FIFO.


Sujet :

Langage C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Octobre 2010
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 50
    Points : 29
    Points
    29
    Par défaut Select et list/FIFO.
    Bonjour a tous!

    Je viens vers vous pour un probleme de select. En effet, j'ai un programme qui fait communiquer different processus entre eux a travers des IPC. Des messages queues pour etre precis. (Ca peut s'apparenter a des listes).

    Ma question est: Est il possible d'utiliser un select pour savoir quand des elements ont ete rajouter sur cette FIFO? Et plus généralement avec les list de la STL?


    Si ca fonctionnait, ca me permettrait de faire un truc vachement plus propre! A moins que vous ayez une solution plus classe a proposer, je suis aussi preneur

    Merci d'avance pour vos reponses!

    edit: Petit precision de taille, je suis sous linux pour coder ^^

  2. #2
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Si ce sont des message queue POSIX et non pas des messages queues System V, et que tu es bien sous Linux, alors oui, les messages queues sont pollables.

    Citation Envoyé par man 7 mq_overview
    On Linux, a message queue descriptor is actually a file descriptor, and can be monitored using select(2), poll(2), or epoll(7). This is not portable.
    (le gras est de moi)
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  3. #3
    Nouveau membre du Club
    Inscrit en
    Octobre 2010
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 50
    Points : 29
    Points
    29
    Par défaut
    Ben j'ai essaye de faire un programme de test. Dans un programme pere, je creer ma message queue, je push dessus, je fork un autre programme avec un exec, ou je recois les message. Et donc dans le pere je fais un select sur le fd de la MQ, et je push dans mon autre programme. Et ca ne debloque pas le select.. Je sais pas d'ou ca vient!

    Aurais tu un exemple de code qui fonctionne? a tout hazard ^^

  4. #4
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Non, je n'ai pas de code, mais ça devrait parcher tout seul. Peux tu poster ton code à toi ?

    Edit: confirme quand même un point : tu utilises bien une MQ Linux (mq_open(), mq_receive()...), et pas une MQ System V (msgget,...)
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Nouveau membre du Club
    Inscrit en
    Octobre 2010
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 50
    Points : 29
    Points
    29
    Par défaut
    Hey bien j'ai utiliser le system V avec les msgget etc. Je ne comprend pas pourquoi ca ne fonctionne pas avec un le fd d'un system V. En plus, dans ts les exemples que j'avais pu trouver (tu me dira j'avais ptet pas assez chercher), c'etait avec le system V, et aucun avec mq_open etc. J'en avais meme jamais entendu parler,c'est pour dire...

    Il faut que je refasse mon truc avec des mq_open alors? Ca marche de la meme facon que le system V? (Si tu a un site avec des exemples, je suis preneur)

    en tout cas, merci de tes interventions, tu m'aide beaucoup! Je comprend vraiment pas pourquoi les fd des msgget ne fonctionne pas avec le select.

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Baradhur Voir le message
    Hey bien j'ai utiliser le system V avec les msgget etc. Je ne comprend pas pourquoi ca ne fonctionne pas avec un le fd d'un system V. En plus, dans ts les exemples que j'avais pu trouver (tu me dira j'avais ptet pas assez chercher), c'etait avec le system V, et aucun avec mq_open etc. J'en avais meme jamais entendu parler,c'est pour dire...

    Il faut que je refasse mon truc avec des mq_open alors? Ca marche de la meme facon que le system V? (Si tu a un site avec des exemples, je suis preneur)

    en tout cas, merci de tes interventions, tu m'aide beaucoup! Je comprend vraiment pas pourquoi les fd des msgget ne fonctionne pas avec le select.
    Il me semble que les IPC System V ne renvoient pas des fd, mais des identifiants - qui ne sont pas partagés avec les processus fils. Je ne suis pas sûr à 100% de ça (sauf en ce qui concerne la partie "pas partagé" )

    Pour récupérer une mq ouverte dans un processus père, il faut refaire un msgctl() avec la clef spécifiée dans le père.

    Sinon, man 7 mq_overview

    Une MQ ouverte avec mq_open pointe bien sur un fd, lui, et ce fd est hérité par tous les processus fils.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <mqueue.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
     
    // link avec -lrt
     
    int main()
    {
      char *buffer;
      mqd_t mq;
      pid_t pid;
      int r;
      struct mq_attr attr;
     
      mq = mq_open("/ma_message_queue", O_RDWR|O_CREAT);
      if (mq == (mqd_t)(-1)) { perror("mq_open"); exit(-1); }
      memset(&attr, 0, sizeof(attr));
      mq_getattr(mq, &attr);
      pid = fork();
      if (pid < 0)
      {
        mq_close(mq);
        perror("fork");
        exit(-2);
      }
      else if (pid == 0)
      {
        // child process
        mq_send(mq, "test", 5, 0);
        exit(0);
      }
      else
      {
        waitpid(pid,NULL,0);
     	buffer = malloc(attr.mq_msgsize);
        r = mq_receive(mq, buffer, attr.mq_msgsize, NULL);
        if (r > 0)
        {
        	printf("message = %s\n", buffer);
        }
        else if (r == 0)
        {
        	printf("no message received\n");
        }
        else
        {
        	perror("mq_receive");
        }
        free(buffer);
        mq_close(mq);
        return 0;
      }
    }
    C'est écrit en C, mais on peut écrire de même en C++ (en beaucoup plus court, en fait).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Nouveau membre du Club
    Inscrit en
    Octobre 2010
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 50
    Points : 29
    Points
    29
    Par défaut
    Merci pour toutes ces precisions! Je pense que j'ai tout ce qu'il me faut maintenant

  8. #8
    Nouveau membre du Club
    Inscrit en
    Octobre 2010
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 50
    Points : 29
    Points
    29
    Par défaut
    Je me permet de poser une derniere question, j'ai du mal a trouver la reponse en cherchant sur le net.

    Dans le cas des MQ du system 5, il faut detruire les MQ avec une fonction specifique, sinon elle reste ouverte meme apres etre sorti du programme. Pour les MQ POSIX, il existe mq_close, mais il ne fait que fermer le file descriptor.

    Est ce qu'il faut comprendre qu'il detruit par la meme la message queue precedement creer? Ou est ce qu'il existe une autre fonction qui permet de definitivement supprimer l'ensemble?

    Merci d'avance!

    edit: J'ai fini par trouver a force de chercher, il faut utiliser mq_unlink pour la fermer definitivement. ^^

  9. #9
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Normallement, fermer tous les descripteurs de fichiers sur la MQ détruit également cette MQ. mq_unlink() a un effet différent en fait : elle supprime le nom de la MQ, mais ne la ferme pas - il est possible de continuer à l'utiliser, à moins que je ne me trompe.

    A noter que mon exemple ne gère pas les permissions sur la MQ lors de l'appel à mq_open(). Il peut être utile de les spécifier de manière explicite.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  10. #10
    Nouveau membre du Club
    Inscrit en
    Octobre 2010
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 50
    Points : 29
    Points
    29
    Par défaut
    Je viens de finir mon programme de test qui marche tout bien avec cette nouvelle version des mq. Malheureusement, je suis toujours bloquer sur mon select...

    Dans mon programme principale, je cree ma mq, je pose 3 messages dessus, ensuite je fork. Dans le fils, je fais un exec, et a l'interieur, je recupere les 3 messages sans problemes. Ensuite je fais un send a l'interieur de mon exec. Dans le pere, a la fin du wait, je fais un mq_receive, je recois bien le message, pas de probleme.

    Mais quand j'essaye de rajouter un select sur mon FD de mq, ben il bloque et rien ne se passe. j'ai mis un sleep pour etre sur qu'on arrive pas sur l'envoie avant que le pere bloque sur le select. Mais rien ne se passe, le programme ne bouge pas sur le select... Peut etre aussi que j'utilise mal ledit select?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    int main()
    {
      struct mq_attr attr;
      mqd_t mq;
     
      attr.mq_maxmsg = 20;
      attr.mq_msgsize = 64;
      attr.mq_flags = 0;
      attr.mq_curmsgs = 0;
     
     mq = mq_open("/ma_queue", (O_RDWR | O_CREAT | O_NONBLOCK), 00666, &attr);
      memset(&attr, 0, sizeof(attr));
      mq_getattr(mq, &attr);
     
      string buf = "TEST TRANSFER";
      mq_send(mq, buf.c_str(), attr.mq_msgsize, 0);
      mq_send(mq, "TEST 2 OMG", (sizeof(char)*64), 0);
      mq_send(mq, "TEST 3 OMFG", (sizeof(char)*64), 0);
     
     
      int rc, i;
      rc = fork();
      if (rc == 0)
        {
          cout << "debut du fils" << endl;
          execv("/home/baradhur/test/thread/thread", NULL);
        }
      else
        {
     
          fd_set read;
          FD_ZERO(&read);
          FD_SET(mq, &read);
          std::cout << "juste avant le select" << std::endl;
          select (mq, &read, NULL, NULL, NULL);
          wait(&i);
          std::cout << "juste apres le wait" << std::endl;
          char *buffer = new char[64];
          mq_receive(mq, buffer, 64, NULL);
          perror("mq_receive apres select");
          cout << "recu de elsewhere : " << buffer << endl;
         }
    }
    Voici le code dans le exec:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    int main()
    { 
      mqd_t mq;                                                          
      struct mq_attr attr;
      sleep(1);                                
     
      mq = mq_open("/ma_queue", (O_RDWR | O_CREAT), 00666, NULL);
     
      memset(&attr, 0, sizeof(attr));
      mq_getattr(mq, &attr);
     
      char *buffer = new char[64];
      int r = mq_receive(mq, buffer, 64, NULL);
      cout << "test IPC 1: " << buffer << endl;
      r = mq_receive(mq, buffer, 64, NULL);
      cout << "test IPC 2: " << buffer << endl;
      r = mq_receive(mq, buffer, 64, NULL);
      cout << "test IPC 3: " << buffer << endl;
     
      mq_send(mq, "TEST RENVOIE", (sizeof(char)*64), 0);
      perror("send from elsewhere");
      mq_close(mq);
      return (0);
    }

    Je me sentirais bete si ca marchais pas pour debloquer le select dans ce cas la aussi


    edit: Je suis un boulet j'avais pas bien fait mon appel au select!
    select (mq + 1, &read, NULL, NULL, NULL);
    Manquait le petit +1... Ca a l'air de marcher tout bien maintenant! Une petite confirmation du meme resultat chez quelqu'un d'autre serait pas de refus

  11. #11
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select (mq + 1, &read, NULL, NULL, NULL);
    Il faut comprendre que select() construit un tableau dont les indices sont les fd qui sont renseignés dans les sets qui lui sont en paramètre. Le premier paramètre est la taille du plus grand des tableaux (donc équal au max(fd1,...,fdn) + 1).

    En outre, à chaque fois que tu attends un message, tu dois attendre au moins attr.mq_msgsize bytes, qui n'est pas nécessairement ce que tu as souhaité (une fois débloqués tes appels à mq_receive, tout se passent beaucoup mieux). Sur mon système, je demande une taille de message de 64 bytes, mais le système me donne une taille de message de 8192 bytes (donc attendre 64 bytes va nécessairement échouer).

    J'ai corrigé tes erreurs, voici l'archive contenant les programmes et un script pour les builder. Il suffit de lancer ./build.sh && ./pere pour voir le résultat.
    Fichiers attachés Fichiers attachés
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  12. #12
    Nouveau membre du Club
    Inscrit en
    Octobre 2010
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 50
    Points : 29
    Points
    29
    Par défaut
    Hey ben, on peut dire que ca c'est du coup de main o_O Merci beaucoup lol Jamais ete aussi bien accompagne

    J'ai bien regarder ce que tu m'avais passer, j'ai bien compris l'ensemble des choses que tu m'a expliquer, j'ai fini l'implémentation dans mon programme, et je suis en phase de test pour vérifier que tout va bien

    Merci encore pour ton aide précieuse!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [SQL] Contrôle "Select" et liste des options
    Par Cantalou dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 02/12/2006, 20h31
  2. Réponses: 2
    Dernier message: 24/11/2006, 10h24
  3. limite nre de selection dans liste deroulante
    Par logone dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 27/06/2006, 12h31
  4. Fonction qui cache en fonction d'une selection de liste
    Par AlphonseBrown dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 20/03/2006, 19h53
  5. Liste FIFO...
    Par blaiseac dans le forum Langage
    Réponses: 1
    Dernier message: 27/07/2005, 15h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo