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 :

Communication entre programmes par mémoire partagée


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2014
    Messages : 12
    Points : 10
    Points
    10
    Par défaut Communication entre programmes par mémoire partagée
    Bonjour à tous,

    Je suis ici aujourd'hui car je souhaite faire communiquer deux programmes entre eux via un espace en mémoire partagé.
    J'ai un programme qui crée un segment mémoire partagée, puis qui récupère les informations qui se trouve dans ce segment.
    Puis un second programmes qui doit écrire à l'intérieur de ce segment mémoire.

    Voici le code de mon premier programme.
    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
     
    int main()
    {
     
        StructAdresse adresseA_Envoyer; 
     
        creerMp(&adresseA_Envoyer);
     
    //Enregistrement des adresses de reception et d'émission
        void * reception = adresseA_Envoyer.adresse_buffer_reception;
        void * emission = adresseA_Envoyer.adresse_buffer_emission;
     
     
    //Définition des structures qui permettrons d'échanger avec le buffer.
        StructBuffer structReception;
        StructBuffer structReceptionTemp;
        StructBuffer structEnvoi;
     
    //initialisation d'un des élément des structures
        strcpy(structReceptionTemp.trame,"null2");
        strcpy(structReception.trame,"vide");
     
     
     
     
    //DEBUG
        strcpy(structEnvoi.nomDst,"nom destination 16");
        strcpy(structEnvoi.nomSrc, "nom source 16");
        strcpy(structEnvoi.trame, "null");
     
        int i=0;
        printf("adresse reception : %p\n",reception);
        printf("adresse emission : %p\n\n",emission);
     
        *((StructBuffer*)reception)=structEnvoi;
     
        while(i<30){
            i++;
    //Lecture message en attente dans le buffer.
            structReception = *((StructBuffer*)reception);
            printf("Message reçu : %s\n",structReception.trame);
     
            sleep(1);
     
            if(strcmp(structReception.trame,structReceptionTemp.trame)!=0){
                printf("Nouveau message reçu depuis %s\n",structReception.nomSrc);
                printf("\t Message : %s",structReception.trame);
                strcpy(structReceptionTemp.trame,structReception.trame);
            }
        }
     
     
        fermerMp(&adresseA_Envoyer);
     
        return 0;
    }
    Voici la fonction utilisé pour créer l'espace mémoire
    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
     
    void creerMp(StructAdresse * aEnvoyer)
    {
     
        char* mem_IDR = (char*) malloc(100*sizeof(char));
        char* mem_IDE = (char*) malloc(100*sizeof(char));
        mem_IDR = "sharedMemoryR";
        mem_IDE = "sharedMemoryE";
     
     
    //L'instruction ftok(name, (key_t) cle) permet de construire une cle identifiant le segment
        key_t clefR = ftok(mem_IDR, (key_t) CLEFA_R);
        key_t clefE = ftok(mem_IDE, (key_t) CLEFA_E);
     
     
        IDR = shmget(clefR,8, IPC_CREAT | IPC_EXCL|SHM_R|SHM_W);
        IDE = shmget(clefE,8, IPC_CREAT | IPC_EXCL|SHM_R|SHM_W); /* Je cherche le segment de mémoire associé
        à la CLEF et je récupère l'identificateur de ce segment mémoire.*/
     
        if (IDR<0 || IDE<0)
        {
            IDR=0;
            IDE=0;
            IDR = shmget(clefR,8,0666);
            IDE = shmget(clefE,8,0666);
     
            if (IDR<0 || IDE<0)
            {
                puts("la création du segment de mémoire à échoué");
                perror("shmget"); // Je m'assure que l'espace mémoire a correctement été crée.
                exit(1);
            }
     
        }
            /* J'attache le segment de mémoire partagée identifié par mem_ID_R au segment de
        donnée du processus de Reception dans une zone libre déterminée par l'OS*/
        aEnvoyer->adresse_buffer_emission = shmat(IDE, NULL,0);
        aEnvoyer->adresse_buffer_reception = shmat(IDR, NULL,0);
     
        aEnvoyer->shmid_emission = IDE;
        aEnvoyer->shmid_reception = IDR;
     
       if(aEnvoyer->adresse_buffer_reception == (void*)-1)
        {
            puts("Un problème est survenue lors de l'afféctation du segment mémoire crée");
            perror("shmat");// Je m'assure que le segment de mémoire à été correctement attaché au process.
            exit(1);
        }
     
     
        if(aEnvoyer->adresse_buffer_emission == (void*)-1)
        {
            puts("Un problème est survenue lors de l'afféctation du segment mémoire crée");
            perror("shmat");// Je m'assure que le segment de mémoire à été correctement attaché au process.
            exit(1);
        }
     
    }

    Et voici le code du second programme qui doit venir écrire à l'intérieur du segment mémoire.

    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
     
     
        StructBuffer aEnvoyer;
     
     
        //MàJ de la structure "aEnvoyer" qui va être écrite dans le buffer de reception du prog DST
                strcpy(aEnvoyer.nomDst, "nomdstTest");
                strcpy(aEnvoyer.trame, "trameTest");
                strcpy(aEnvoyer.nomSrc, "nomSrcTest");
                recupAdresseBufferReception_Nom(&aEnvoyer);
     
                printf("Le programme source est : %s\n",aEnvoyer.nomSrc);
                printf("Le programme de destination est : %s \n",aEnvoyer.nomDst);
                printf("Message transmit : %s\n",aEnvoyer.trame);
                printf("\tAdresse cible pour l'écriture : %p\n\n",aEnvoyer.ptr_adresse_buffer);
     
        //Récupération des info lié au segment de mémoire partagé
                recupSegmentMemoire();
     
        //Ecriture dans le buffer du premier programme
                *((StructBuffer*)aEnvoyer.ptr_adresse_buffer)=aEnvoyer;
                puts("message ecrit dans le buffer");
    Et voici la fonction que j'utilise pour récupérer l'accès au segment mémoire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void recupSegmentMemoire()
    {
     
        printf("\n\n --SHMID--  : %d\n",carnetAdresses[0].shmid_reception);
        if((shmctl(carnetAdresses[0].shmid_reception,IPC_STAT,NULL))!=0){
            puts("problème lors de l'accès au segment mémoire");
            perror("Shmctl : ");
            exit(EXIT_FAILURE);
        }
     
    }
    Et enfin voici la structure structBuffer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct StructBuffer{
        int synchro;
        char nomDst[40];
        char nomSrc[40];
        char trame[40];
        void* ptr_adresse_buffer;
    };
    Voilà pour mon code, donc toute la partie lié au premier code fonctionne comme je le souhaite, en tout cas en apparence. Pour le second programme je récupère bien toutes les informations que je souhaite.
    Par contre je n'arrive pas à accéder à l'espace mémoire créer depuis le second programmes.

    J'ai essayé plusieurs méthodes et j'ai fait de nombreuses recherches mais je n'arrive pas a trouver la solutions à mon problèmes.

    Je vous remercie pour vos pistes et votre aide.

  2. #2
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Points : 7 163
    Points
    7 163
    Par défaut
    La description de ton problème n'est pas claire. De plus tu ne donnes pas tout le code, seulement des morceaux.
    Dans ton second programme, je ne vois pas de shmat ?
    Pour les mémoires partagées, j'utilise shm_open au lieu de shmget. Ca permet de donner un nom à la manière d'un fichier et donc de construire un nom unique.
    Par exemple, la première SHM pourrait avoir comme nom "/mon_programme_emission". La création d'une SHM se fait en une seule ligne, pas besoin de ftok.
    Ensuite pourquoi avoir deux SHM ? D'après ton code, j'ai compris que chaque SHM ne contient qu'une seule structure qui ne dépasse pas 1 Ko. Pourquoi ne pas utiliser une seule SHM qui contient une structure du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct
    {
      StructBuffer emission;
      StructBuffer reception;
    }
    Enfin, comment comptes-tu synchroniser et gérer les attentes de lecture/écriture entre les deux processus ? Tu n'as pas mis de sémaphore ?
    Ou comptes-tu utiliser une pause dans un while en attendant que le champ "synchro" de tes structures change de valeur ?

    Quitte à utiliser de l'IPC (SHM + sémaphore), pourquoi ne pas utiliser une queue de messages ? Ta structure semble de petite taille et ça simplifierait grandement la synchronisation entre tes processus.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2014
    Messages : 12
    Points : 10
    Points
    10
    Par défaut
    Bonjour dinobogan,

    Merci pour toute ces remarques, elle me font prendre conscience qu'il y a plusieurs choses aux quelles je n'ai pas pensé.

    Je vais me re pencher sur mon code en prenant en compte ces remarques et le repenser.

Discussions similaires

  1. Communication entre programmes
    Par pdgnr dans le forum Windows Forms
    Réponses: 2
    Dernier message: 16/08/2007, 18h33
  2. Réponses: 4
    Dernier message: 13/06/2007, 18h41
  3. communication entre programme
    Par nixonne dans le forum C++Builder
    Réponses: 3
    Dernier message: 27/06/2006, 14h35
  4. communication entre programmes
    Par nixonne dans le forum C++
    Réponses: 11
    Dernier message: 16/06/2006, 21h04
  5. communication entre programmes
    Par jérôme dans le forum C
    Réponses: 12
    Dernier message: 16/04/2002, 09h05

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