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 :

Liste chainée en mémoire partagée


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut Liste chainée en mémoire partagée
    Je souhaite créer une liste chainée partagée entre 2 programmes, l'un écrit les données, l'autre les lit, donc pas de problème de conflit.
    Le problème étant que je n'ai rien trouvé de mieu que de créer une mémoire partagée PAR élement de ma liste chainée.
    De plus, étant donné qu'il faut avoir la même clé pour les deux applications, par élément qui existent dans la liste, j'ai utilisé ftok qui est sensé donner une clé par couple (url,pid), en lui donnant toujours le même pid et un pid bidon que je fais commencer à 0 et que j'incrémente à chaque nouvel élément que je crée, le tout dans l'espoir que ma clé soit la même sur les deux programmes.

    Voilà déjà je trouve ça un peu moyen, mais je n'ai rien trouvé de mieu.
    Qu'en pensez-vous? Pourrais-je faire autrement?

    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    typedef struct s_shared_elem
    {
        char c;
        struct s_shared_elem* next;
        struct s_shared_elem* previous;
    }shared_elem;
     
    typedef struct s_shared_list
    {
        s_shared_elem* first;
        s_shared_elem* last;
    }shared_list;
     
    int forthekey = 0;
    char* url="/home/toor/Projet_cgi/";
     
    shared_elem* shared_malloc(int pid, const char* url)
    {
            shared_elem* shm;
            int shmid;
            int key=ftok(url,pid);
            if((shmid=shmget(key,1,IPC_CREAT | 0666)) < 0)
            {   
                perror("shmget");
                exit(1);
            }   
     
            if ((shm = shmat(shmid,NULL,0)) == (shared_elem*)-1)
            {
                 perror("shmat");
                 exit(1);
            }
            return shm;
    }
     
    void Init_shared_list(shared_list* liste)
    {
        liste->first = NULL;
        liste->last = NULL;
    }
     
    void Ajouter_elem(shared_list* liste)
    {
        shared_elem* new = shared_malloc(pid,url);
        new->next = NULL;
        new->previous = liste->last;
     
        if(liste->first == NULL)
        {
            liste->first = new;
            liste->last = new;
        }
     
        else
        {
            liste->last->next = new;
            liste->last = new;
        }
     
        forthekey++;
    }
     
    void shared_free(shared_elem* todelete,int pid, const char* url)
    {
        shared_elem* shm;
        int shmid;
        int key=ftok(url,pid);
        if((shmid=shmget(key,1,IPC_CREAT | 0666)) < 0)
        {
            perror("shmget");
            exit(1);
        }
        shmdt(todelete);
        shmctl(shmid,IPC_RMID,NULL);
     
        forthekey--;
    }
     
    void Delete_list(shared_list* liste)
    {
        while(liste->last != liste->first)
        {
            shared_elem* tmp=liste->last;
            liste->last=liste->last->previous;
            Shared_free(tmp,pid,url);
        }
        Shared_free(liste->first,pid,url);
    }

  2. #2
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par drogeek Voir le message
    Je souhaite créer une liste chainée partagée entre 2 programmes, l'un écrit les données, l'autre les lit, donc pas de problème de conflit.
    Je ne voudrais pas paraître rabat-joie, mais le fait qu'un processus écrive et l'autre lise n'est pas suffisant pour garantir qu'il n'y aura pas de problèmes. Le lecteur peut lire un nœud qui est dans un état incohérent (à moitié écrit) ce qui pourrait être problématique.
    Par exemple ton code pour l'ajout du premier élément est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            liste->first = new;
            liste->last = new;
    Imagine qu'entre ces deux lignes exécutées par le producteur, c'est-à-dire que le producteur a mis liste->first à jour mais n'a pas encore mis liste->last à jour, le consommateur fasse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // La liste est-elle non vide ?
    if (liste->first!=NULL) {
      // ici la liste n'est pas vide puisque first n'est pas NULL
      // mais contient-elle plus d'un élément ?
      if (liste->first != liste->last) {
        // ici la liste doit contenir plus d'un élément puisque first et last 
        // ne pointent pas sur le même endroit
        // affichons le second
        printf("%s\n", liste->first->next->string); // Mais pourquoi ça plante ???
       ....
    Citation Envoyé par drogeek Voir le message
    Le problème étant que je n'ai rien trouvé de mieu que de créer une mémoire partagée PAR élement de ma liste chainée.
    Utiliser un shmget pour chaque élément de ta liste va rendre ton OS fou. Il y a des limites système sur le nombre total de segments partagés (la man page de shmget mentionne 4096 system wide segments pour les versions actuelles de noyau linux), une mauvaise utilisation de ta mémoire partagée pourrait pénaliser tout le système : une bonne raison pour ne pas procéder ainsi.

    Citation Envoyé par drogeek Voir le message
    Voilà déjà je trouve ça un peu moyen, mais je n'ai rien trouvé de mieu.
    Qu'en pensez-vous? Pourrais-je faire autrement?
    Faire autrement ? Sans doute
    La première question à se poser est certainement : a-t-on besoin de partager la structure «liste chaînée» sachant qu'en lisant ton code en diagonale tu sembles vouloir créer une file (tu n'ajoutes un élément qu'en queue).

    Pour le déterminer il faut savoir combien de processus entrent en jeu. Il est établit qu'il n'y a qu'un unique producteur, intéressons-nous au nombre de consommateurs.
    S'il n'y a qu'un consommateur alors tu devrais t'orienter vers une autre IPC (fifo par exemple).
    S'il y a plusieurs consommateurs et que les messages n'ont pas à être délivrés à tous les consommateurs alors fifo aussi (modèle dispatcher/worker, le producteur donne du boulot aux consommateurs mais chaque consommateur fait un boulot différent).
    S'il y a plusieurs consommateurs et qu'ils doivent tous être capables à tout moment d'accéder à la totalité des messages alors oui il faudra une sorte de liste.

    Comme apparemment tu n'ajoutes qu'en fin de liste, que tu ne supprimes pas les éléments mais toute la liste d'un coup je dirais qu'un simple tableau ferait l'affaire.
    Tu crées une grosse mémoire partagée mais limitée (peu importe la méthode que ce soit shmget ou mmap ou via un fichier ou ...). Le producteur et les consommateurs auront des adresses mémoires différentes mais le ième maillon sera toujours au même endroit, et le suivant de ce maillon sera le maillon i+1. Évidemment il faudra quand même faire attention au problèmes d'atomicité et de synchronisation, mais tu n'as plus besoin de te prendre la tête pour avoir le même espace d'adresses dans chaque processus.

    Bon ça dépend aussi du volume de donnée auquel tu vas faire face et de l'utilisation exacte de ta chaîne.

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    Comme ta mémoire pourra être mappée avec des adresses différentes avec tes deux processus, un même emplacement n'aura pas forcément la même adresse dans tes deux processus.

    En C++, on a des "pointeurs intelligents", mais en C, je pense qu'il te faudrait, à la place d'un pointeur, stocker un entier donnant le nombre d'octet entre l'emplacement visé et le début de ta zone mémoire partagée.

    Ainsi il te suffirait d'écrire cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Type * t = (Type *)( (char *)debutZonePartagee + offset )
    Pour récupérer ton pointeur dans ton processus.

    Tu peux même écrire une macro :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define mapPTR( ZonePartagee, Type, Offset ) (  (Type *)( (char *)(ZonePartagee) + (Offset) )  )

Discussions similaires

  1. Partage d'une liste chainée entre Processus
    Par la_chevre dans le forum Débuter
    Réponses: 7
    Dernier message: 09/10/2008, 12h35
  2. C-System : Memoire partagée et Liste chainée
    Par agrosjea dans le forum C
    Réponses: 3
    Dernier message: 18/06/2008, 09h58
  3. Liste chainé et fuite mémoire
    Par poussinphp dans le forum C++
    Réponses: 2
    Dernier message: 25/04/2007, 23h06
  4. mémoire et liste chainée?
    Par tintin72 dans le forum C++
    Réponses: 17
    Dernier message: 17/12/2005, 20h54
  5. Réponses: 24
    Dernier message: 30/10/2005, 09h27

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