File de message, pere-fils sous unix

Résolu
cs_adri85 Messages postés 18 Date d'inscription jeudi 22 février 2007 Statut Membre Dernière intervention 21 septembre 2009 - 4 mars 2007 à 12:41
cs_adri85 Messages postés 18 Date d'inscription jeudi 22 février 2007 Statut Membre Dernière intervention 21 septembre 2009 - 7 mars 2007 à 14:19
Bonjour,

je souhaite que le processus père de mon application envoie 2 nombres entiers plus un opérande ( + - * / %) a un fils par le biais d'une file de message.
mon problème est de passer les paramètres au fils par la file de mess car j'ai 2 int et 1 char!!
Est ce que vous pouvez m'aider sur ce point svp

merci

11 réponses

ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
7 mars 2007 à 11:31
salut,

une solution serait :
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <sys/time.h>

#define CLEF_REQUETES         0x00012347
#define LG_MAX                512

struct msgform {
      long mtype;                        //type de message
      struct minfo {
            int mnombre[3];         //nombres
            char mtext;       //opérande
      }donnees;
} msg;

int res;
int frequete;
//FIX : ne pas oublier d'initialiser les variables avant de les utiliser
int length = sizeof(struct minfo);

int main(int argc,char *argv[])
{
    pid_t fils;
    int nombre1;
    int nombre2;
    char operation;
    int status;

    //On crée une file de message
    frequete = msgget(CLEF_REQUETES, IPC_CREAT | 0700);
    if (frequete == -1) { perror("msgget"); return (EXIT_FAILURE);}

      while (1)
      {
            //on demande à l'utilisateur l'opération à effectuer
            printf("entrez nombre1\n");
            scanf("%d", &nombre1);

            printf("entrez nombre2\n");
            scanf("%d", &nombre2);

            fflush(stdin);
            printf("opération : +,-,*,/ ?\n");
           
        //FIX : lecture d'un char
            int c;
            while ((c = getchar()) != EOF && c != '\n');
            operation = getchar();
           
            //on récupère le texte
            msg.donnees.mnombre[0] = nombre1;
            msg.donnees.mnombre[1] = nombre2;
            msg.donnees.mtext = operation;
            //On créé le fils
            fils = fork();

        //FIX : plus claire avec un switch
        //fork renvoie -1 ou 0 ou <> 0
        //étant donné qu'un int est signé, un PID peut être < 0
            switch(fils)
            {
                case -1:
                    perror("Fork");
                    return (EXIT_FAILURE);
                    break;
            case 0:
                  //on récupère les infos de la file de message
                  //FIX : utiliser un mtype fixe
                  //FIX : utiliser un mtype != pour distiguer le sens père -> fils
                  //et fils -> père
                  res = msgrcv(frequete, &msg,length, 1, 0);
                  if (res == -1) { perror("msgrcv"); exit(0); }
                                   
                  switch(msg.donnees.mtext)
                  {
                        case '+' :res = msg.donnees.mnombre[0] + msg.donnees.mnombre[1];break;
                        case '-' :res = msg.donnees.mnombre[0] - msg.donnees.mnombre[1];break;
                        case '*' :res = msg.donnees.mnombre[0] * msg.donnees.mnombre[1];break;
                        case '/' :if(msg.donnees.mnombre[1] != 0)
                               {
                                   res = msg.donnees.mnombre[0] / msg.donnees.mnombre[1];}
                               else {printf("division par 0 interdite"); exit(0);}break;
                  }
                  msg.donnees.mnombre[2] = res;
          //FIX : renvoie du résultat avec un mtype !=
          //sinon, si on un seul mtype, le père relit son message et le fils rien
                  msg.mtype = 2;
                  if( msgsnd(frequete, &msg, length, 0) == -1) { perror("msgsnd"); exit(0);}
                    //FIX : ne pas oublier d'arrêter le fils
                  return EXIT_SUCCESS;
                  break;
        default:
                  //On envoie le message sur la file de message
                  msg.mtype = 1;
                  res = msgsnd(frequete, &msg, length, 0);
                  if (res == -1) { perror("msgsnd"); return (EXIT_FAILURE);}

                  //on récupère les infos sur la file de message
                  res = msgrcv(frequete, &msg,length, 2, 0);
                  if (res == -1) { perror("msgrcv"); exit(0); }
                  //FIX : c'est mieux d'utiliser deux mtype
                  //car la forme du message est identique mais la signification est !=
                  //de plus, je ne sais pas bien si le waitpid était vraiment propre
                  //waitpid(fils,&status,0);

                  //On affiche le message traduit
                  printf("result : %d\n", msg.donnees.mnombre[2]);
                  break;
            }
      }
}

j'ai mis des //FIX au endroit où il y avait un prb...

ShareVB
3
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
4 mars 2007 à 22:13
salut,

http://users.actcom.co.il/~choo/lupg/tutorials/multi-process/multi-process.html

à priori, dans msgbuf, tu mets ce que tu veux donc 2 int et 1 char par ex...

ShareVB
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
4 mars 2007 à 22:14
0
cs_adri85 Messages postés 18 Date d'inscription jeudi 22 février 2007 Statut Membre Dernière intervention 21 septembre 2009
5 mars 2007 à 09:19
Je sais qu'il est possible de mettre des infos de types différents mais je sais pas comment le faire

Normalement une structure msgbuf est de la forme : struct msgbuf { long mtype; char mtex[];}msg;
Donc dans mtext je peux pas mettre de int!!
Ce que j'ai fait c'est :  struct msgbuf { long mtype; struct minfo { int mnombre[]; char mtext[]}msgdonnees;}msg;

A la compilation ça passe mais à l'éxécutioin j'ai une erreur de segmentation. Je sait pas d'où ça vient??
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
5 mars 2007 à 10:38
salut,

rien ne t'empeche de faire :
struct msgbuf {
    long mtype;     /* message type, a positive number (cannot be zero). */
    char car;
    int i;
    int j;
};


par contre tu ne dois pas inclure de pointeurs, il faut obligatoirement avoir des tableaux de tailles fixes...car msgsnd copie une zone mémoire...

donc tu ne peux pas faire :
struct msgbuf { long mtype; struct minfo { int mnombre[]; char mtext[]}msgdonnees;}msg;
par contre, tu peux faire :
struct msgbuf { long mtype; struct minfo { int mnombre[256]; char mtext[256]}msgdonnees;}msg;

ShareVB
0
cs_adri85 Messages postés 18 Date d'inscription jeudi 22 février 2007 Statut Membre Dernière intervention 21 septembre 2009
5 mars 2007 à 11:06
salut,

C'est bien comme ça que je l'ai déclarée, nous sommes d'accord sur ce point. Donc mon erreur ne vient pas de là.
Dans le msgsnd et msgrcv on a besoin de donnée la longeur du paramètre mtext.
Donc vu que j'ai une structure minfo je fait : length = sizeoff(struct minfo) - sizeoff (long);

length est utilisé par le père et par le fils donc je l'ai déclarée et initialisée en globale ( en dehors de toute fonction). Je ne suis pas sur que ça soit ok et que mon erreur de segmentation ne vienne pas de là.

Qu'en pense tu??
merci pour ton aide

Adri85
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
5 mars 2007 à 12:12
salut,

donne le code en entier s'il n'est pas trop gros (sinon en MP)...ca sera plus simple...

ShareVB
0
cs_adri85 Messages postés 18 Date d'inscription jeudi 22 février 2007 Statut Membre Dernière intervention 21 septembre 2009
5 mars 2007 à 16:12
je t'ai envoyer le code en message privé!!
Je te laisse regarder si tu remarque des erreurs.
Salut
Adri85
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
5 mars 2007 à 17:48
salut,

euh, je pense que tu ne devrais pas mélanger les signaux et les files de messages par ce que là, il y en a dans tous les sens...et les fils lancent des fils qui lancent des fils qui ne se terminent jamais donc...

le plus simple serait de faire :
dans une boucle :
-> un père qui demande les valeurs, les envoient au fils (msgsnd) , attend la réponse du fils (msgrcv), affiche le résultat
-> un fils qui reçoit (msgrcv), qui calcule et renvoie le résultat (msgrcv) puis qui se TERMINE (return ou exit)

ou encore, créer le fils puis dans une boucle, envoyer les données au fils, calcul dans le fils, affichage dans le père

et le tout sans signaux...

ShareVB
0
cs_adri85 Messages postés 18 Date d'inscription jeudi 22 février 2007 Statut Membre Dernière intervention 21 septembre 2009
5 mars 2007 à 20:30
j'ai essayé un nouveau code comme tu me l'as conseillé. Cependant l'exe reste bloquée sur scanf ( "%c", operation);

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <sys/time.h>

#define CLEF_REQUETES         0x00012347
#define LG_MAX                512

struct msgform {
      long mtype;                        //type de message
      struct minfo {
            int mnombre[3];         //nombres
            char mtext;       //opérande
      }donnees;
} msg;

int res;
int frequete;
int length;

int main(int argc,char *argv[])
{
    pid_t fils;
    int nombre1;
    int nombre2;
    char operation;
    int status;

    //On crée une file de message
    frequete = msgget(CLEF_REQUETES, IPC_CREAT | 0700);
    if (frequete == -1) { perror("msgget"); return (EXIT_FAILURE);}

    msg.mtype = getpid();

      while (1)
      {
            //on demande à l'utilisateur l'opération à effectuer
            printf("entrez nombre1\n");
            scanf("%d", &nombre1);

            printf("entrez nombre2\n");
            scanf("%d", &nombre2);

            printf("opération : +,-,*,/ ?\n");
            scanf("%s", operation);
            printf("aaa");
            //on récupère le texte
            msg.donnees.mnombre[0] = nombre1;
            msg.donnees.mnombre[1] = nombre2;
            msg.donnees.mtext = operation;
            printf("ddd");
            //On créé le fils
            fils = fork();

            if (fils < 0) { printf("erreur au fork"); return (EXIT_FAILURE);}

            //Si on est dans le père
            if (fils > 0)
            {
                  //On envoie le message sur la file de message
                  res = msgsnd(frequete, & msg, length + 1, 0);
                  if (res == -1) { perror("msgsnd"); return (EXIT_FAILURE);}

                  waitpid(fils,&status,0);
                  //on récupère les infos sur la file de message
                  res = msgrcv(frequete, & msg,length , getpid(), 0);
                  if (res == -1) { perror("msgrcv"); exit(0); }

                  //On affiche le message traduit
                  printf("result : %d\n", msg.donnees.mnombre[2]);
            }

            //Si on est dans le fil
            if ( fils == 0)
            {
                  //on récupère les infos de la file de message
                  res = msgrcv(frequete, & msg,length , getpid(), 0);
                  if (res == -1) { perror("msgrcv"); exit(0); }
     
                  switch(msg.donnees.mtext)
                  {
                        case '+' :res = msg.donnees.mnombre[0] + msg.donnees.mnombre[1];break;
                        case '-' :res = msg.donnees.mnombre[0] - msg.donnees.mnombre[1];break;
                        case '*' :res = msg.donnees.mnombre[0] * msg.donnees.mnombre[1];break;
                        case '/' :if(msg.donnees.mnombre[1] != 0)
                               {
                                   res = msg.donnees.mnombre[0] / msg.donnees.mnombre[1];}
                               else {printf("division par 0 interdite"); exit(0);}break;
                        /*case '%' :res = (msg.minfo.mnombre[0] * msg.minfo.mnombre[1])/100;
                             break;*/
                  }
                  msg.donnees.mnombre[2] = res;
                  if( msgsnd(frequete, & msg, length + 1, 0) == -1) { perror("msgsnd"); exit(0);}  
                  exit(0);         
            }
      }}<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>
0
cs_adri85 Messages postés 18 Date d'inscription jeudi 22 février 2007 Statut Membre Dernière intervention 21 septembre 2009
7 mars 2007 à 14:19
Salut!

Merci infiniment ça fonctionne parfaitement!!
C'est vraiment cool!

Adri85
0
Rejoignez-nous