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

C Discussion :

Inter-Processus Communication: fil de messages (demande d'explications)


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Mars 2009
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2009
    Messages : 68
    Points : 56
    Points
    56
    Par défaut Inter-Processus Communication: fil de messages (demande d'explications)
    Bonjour à tous,

    Je cherche un explication au fonctionnement de la communication inter-processus appelée fil de messages. J'ai plus particulièrement un problème avec les fonctions d'envoie (msgsnd) et de réception (msgrcv).

    Si je reprends les entêtes de ces fonctions telles que j'ai pu les trouver dans la doc, les voici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long int msgtyp, int msgflg);
    En ce qui concerne le premier paramètre, c'est assez clair: il s'agit de l'identifiant de notre BAL(Boîte Aux Lettres).

    La suite est moins clair. Pour utiliser cette boîte aux lettres, il faut définir une structure de la forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct msg{
      long int mtype;
      char mtext[1];
    };
    Soit! Mais alors voici mes questions:

    1°) Le deuxième paramètre est un pointeur sur notre structure. Mais alors que se passe t-il lors de l'envoi ou de la réception d'un message.
    Qu'envoie t-on? Envoie t-on la structure?

    Considérons deux processus: un écrivain qui écrit dans la BAL et un lecteur qui vient y chercher des messages.
    Je déclare une variable message de type "struct msg" dans l'écrivain. Et j'écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    msgsnd(id_bal,&message,sizeof(mtext),0)
    Que signifie cette ligne? J'envoie dans la BAL identifiée par bal_id, un message de type struct msg de taille mtext sans option? Mais alors pourquoi ce "&"???

    Même chose pour le lecteur. J'y déclare une variable message de type "struct msg" et j'écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    msgrcv(id_bal,&message,sizeof(mtext),1,0)
    Je vais chercher dans la BAL identifiée par bal_id un message de type struct msg de type 1 et de taille mtext). Mais que se passe t-il en réalité? Je copie ce qu'il y a dans la BAL dans ma structure message???

    2°) Pourquoi le troisième paramètre (size) ne concerne que la chaîne de caractères contenu dans la structure et non la structure elle-même? Du même coup, comment est-il possible par la suite de récupérer différents messages d'un type particulier au sein d'un même BAL si ce qui est envoyé n'est que la chaîne de caractères?



    Merci d'avance pour votre temps et vos réponses!

  2. #2
    Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Mars 2009
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2009
    Messages : 68
    Points : 56
    Points
    56
    Par défaut
    Je me rends compte que j'ai peut-être mal posé la question et je m'en excuse.

    1°) Je voudrais savoir ce qu'on envoie réellement dans la queue de messages (structure, chaîne de caractères)?
    2°) Je voudrais comprendre pourquoi ce "&" dans les arguments de ma fonction.


    Merci encore

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Bonjour,

    Tout d'abord, il ne s'agit pas de « un fil de messages » mais de « une file de messages ». Sur ce point, je crois que l'on est d'accord.

    Pour le reste, si on lit la man page, on voit :

    Pour envoyer ou recevoir un message, le processus appelant alloue une structure comme celle-ci :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct msgbuf {
      long  mtype;    /* type de message ( > 0 ) */
      char  mtext[1]; /* contenu du message      */
    };
    et la même en anglais :

    The msgp argument is a pointer to caller-defined structure of the following general form:
    Cela veut dire, d'une part, qu'un message est défini par deux choses : un nombre entier positif censé représenter son « type » et par une chaîne de texte qui définit le message proprement dit. Cela signifie également que la taille de ton buffer « mtext » est laissé à ta discrétion.

    On te demande simplement de monter une structure de façon à ce que les deux données se trouvent au même endroit, mais tu dois quand même préciser la taille du texte à envoyer dans les paramètres de ta fonction. Évidemment, il aurait été plus cohérent de préciser cette taille dans un champ de la même structure, voire même, si celle si n'était plus amenée à évoluer dans le temps, à ajouter le type comme un paramètre supplémentaire de msgsnd(), à faire pointer msgp vers un buffer ordinaire et abandonner purement et simplement la structure.

  4. #4
    Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Mars 2009
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2009
    Messages : 68
    Points : 56
    Points
    56
    Par défaut
    Je te remercie pour ta réponse bien qu'elle ne m'apporte pas beaucoup de nouveaux éléments.

    Que se passe t-il quand j'utilise msgsnd()? J'envoie ma structure toute entière?

    Et avec msgrcv? Je recopie la structure reçue dans une structure locale?

    N.B: Si je me penche sur cette question, c'est que j'utilise une file de message pour transmettre une phrase d'un processus à un autre. A la réception au lieu de retrouver mon message je reçois ce caractère bizarre:

    

    Alors je me disais que peut être je ne recevais pas une chaîne, mais une structure ou autre chose...


    Merci

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Marco88 Voir le message
    Que se passe t-il quand j'utilise msgsnd()? J'envoie ma structure toute entière? Et avec msgrcv? Je recopie la structure reçue dans une structure locale?
    Oui. Dans les deux cas (émetteur et récepteur), tu définis une structure comme ci-dessus, dont tu enverras le contenu ou qui te servira à le recevoir.

    La particuliarité, c'est que c'est toi qui définit la taille de mtext, c'est-à-dire que tu remplaces « [1] » par la valeur de ton choix. Dès lors, comme la fonction ne peut connaître à l'avance la taille de ce champ, tu es obligé de la préciser à l'appel de ta fonction.

    Si les tailles de chaque côté ne correspondent pas, et que le message à recevoir est trop gros pour ton buffer, tu as deux choix. Selon l'état d'un flag, soit le message est tronqué, soit l'appel échoue :

    l'appel système msgrcv lit un message depuis la file indiquée par msqid dans la structure msgbuf pointée par l'argument msgp, en extrayant le message en cas de réussite.
    L'argument msgsz indique la taille maximale en octets du membre mtext de la structure pointée par l'argument msgp. Si le contenu du message est plus long que msgsz octets, et si l'argument msgflg contient MSG_NOERROR, alors le message sera tronqué (et la partie tronquée sera perdue). Sinon le message ne sera pas extrait de la file, et l'appel système échouera en indiquant E2BIG dans errno.

  6. #6
    Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Mars 2009
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2009
    Messages : 68
    Points : 56
    Points
    56
    Par défaut
    Après avoir vérifié, l'erreur ne vient pas de la taille spécifiée aux fonctions (j'utilise à l'émetteur et au récepteur une même constante).

    Qu'est-ce qui pourrait provoquer l'affichage d'un tel caractère?

    Voilà la partie de mon code concerné:

    Structure déclarée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct monmsg{
      long type;
      char Datagramme[TAILLE_DATA + NUM_NBR];
    };

    _ pour l'émetteur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    struct monmsg msg1 = {1,"1244Phrase_codée"};
     
    main(int argc, char **argv)
      {
        bal_ID = msgget(CLE_BAL,0666);
        msgsnd(bal_ID,&msg1,sizeof(msg1.Datagramme),0);
    [...]
      }
    _ pour le récepteur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int bal_ID;
    struct monmsg message1;
     
            bal_ID = Creation_BAL();
            message1.type = 1;
            for (;;)
              {
                Lecture_BAL(bal_ID,message1);
                printf("Dans la bal il y a %s\n",message1.Datagramme);
    avec les fonctions Creation_BAL et Lecture_BAL suivantes:
    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
     
    int Creation_BAL()
      {
        int val;
        val = msgget(CLE_BAL, 0666|IPC_CREAT);   // création de la boîte aux lettres
        return val;
      }
     
     
    int Lecture_BAL(int bal_ID, struct monmsg message)
      {
        int rep;
        if ((rep = msgrcv(bal_ID,&message,sizeof(message.Datagramme),message.type,0)) == -1)            // Lecture des messages de type Msg.type dans la BAL
          {
            perror("Erreur de lecture dans la boîte aux lettres\n");
            exit (1);
          }
        else
          {
            return rep;
          }
      }
    N.B: CLE_BAL est définie dans un .h et est donc commune aux deux processus.

    Et le programme retourne:
    Dans la bal il y a 

    Merci

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Ici :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            Lecture_BAL(bal_ID,message1);
            printf("Dans la bal il y a %s\n",message1.Datagramme);
    
    int Lecture_BAL(int bal_ID, struct monmsg message)
    {
        …
    }

    En procédant ainsi, tu transmets le contenu de ta structure à ta fonction Lecture_Bal() par copie. Le paramètre « message » est alors vu comme une variable locale. C'est l'adresse de celle-ci que tu utilises, et cette variable est perdue lorsque tu quittes ta fonction. Et, en tout état de cause, elle reste strictement indépendante de celle que tu déclares dans main().

    Si tu veux procéder ainsi, il faut passer un pointeur vers une telle structure à ta fonction Lecture_Bal(), et l'utiliser directement à la place de « & » :

    Code C : 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
    int Lecture_BAL(int bal_ID, struct monmsg * message)
    {
        …
        if ((rep = msgrcv(bal_ID,message,sizeof(message->Datagramme),message->type,0)) == -1)
        …
    }
    
    int main (void)
    {
            bal_ID = Creation_BAL();
            message1.type = 1;
            for (;;)
              {
                Lecture_BAL(bal_ID,&message1);
                printf("Dans la bal il y a %s\n",message1.Datagramme); }
    
        return 0;
    }

  8. #8
    Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Mars 2009
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2009
    Messages : 68
    Points : 56
    Points
    56
    Par défaut
    Génial!!!

    L'erreur était bien là!

    Alors comme ça n'est pas évident pour moi je vais essayer de récapituler et attendre confirmation avant de mettre le sujet en résolu.

    En réalité, je déclarais une variable message1 (de type struct) dans le main que j'envoyais à ma fonction Lecture_BAL() par copie. Ma fonction voyait cette structure comme une variable locale vu la manière dont je la déclarais en paramètre. Elle y faisait donc des changements mais perdait cette variable locale à la fin. Je n'avais donc en réalité rien changé dans ma structure déclarée dans mon main.

    La solution consiste donc à envoyer à ma fonction non plus une copie de ma structure, mais l'adresse de ma variable message1. Ainsi, les changements opérés par fonction Lecture_BAL() s'effectuent bien sur ma variable message1 déclarée dans mon main.

    Ai-je bien compris?

    Merci encore pour ta patience et pour tes réponses

    Cordialement.

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Marco88 Voir le message
    En réalité, je déclarais une variable message1 (de type struct)
    Plus précisément, de type « struct monmsg { long type; char Datagramme[TAILLE_DATA + NUM_NBR]; }; ». « struct » seul est insuffisant pour définir un type.

    … dans le main que j'envoyais à ma fonction Lecture_BAL() par copie. Ma fonction voyait cette structure comme une variable locale vu la manière dont je la déclarais en paramètre. Elle y faisait donc des changements mais perdait cette variable locale à la fin. Je n'avais donc en réalité rien changé dans ma structure déclarée dans mon main.

    La solution consiste donc à envoyer à ma fonction non plus une copie de ma structure, mais l'adresse de ma variable message1. Ainsi, les changements opérés par fonction Lecture_BAL() s'effectuent bien sur ma variable message1 déclarée dans mon main.

    Ai-je bien compris?
    C'est exactement cela.

    À noter que l'opérateur « & » en tant que préfixe sert à obtenir l'adresse d'une variable (et donc un pointeur). C'est pour cela que l'on a passé directement cette adresse à la fonction.

    Toutefois, pour être tout-à-fait complet, il faut également préciser que le passage d'un tableau en tant qu'argument de fonction est un problème fréquent en C, mais que quand il fait partie d'une structure, la taille de celle-ci est alors connue et tu peux donc la renvoyer en retour de fonction comme la passer en paramètre. Dans l'absolu, donc, tu pourrais faire un return de la variable locale que tu as modifiée. Cependant, la méthode est généralement à proscrire car les buffers ont habituellement une grande taille.

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

Discussions similaires

  1. [windows] Communication inter-processus
    Par litbos dans le forum Windows
    Réponses: 6
    Dernier message: 16/01/2007, 10h13
  2. Processus: communication du fils vers le pere
    Par Trunks dans le forum POSIX
    Réponses: 6
    Dernier message: 16/11/2006, 18h21
  3. [Perl] communication Inter-Processus
    Par MarneusCalgarXP dans le forum Langage
    Réponses: 15
    Dernier message: 14/08/2006, 23h43
  4. [débutant] Communication inter-processus
    Par tooney dans le forum C
    Réponses: 3
    Dernier message: 29/12/2005, 21h48
  5. communication inter-processus
    Par benoit70 dans le forum MFC
    Réponses: 1
    Dernier message: 14/04/2005, 10h55

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