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 :

[Linux / Unix] Utilisation de mmap et munmap pour stocker des structures C.


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 56
    Points : 44
    Points
    44
    Par défaut [Linux / Unix] Utilisation de mmap et munmap pour stocker des structures C.
    Bonjour

    Je suis en train de faire un petit programme avec mmap permetant de gerer des utilisateurs.
    J'ai cependant un petit soucis.

    J'ecris mes structures dans le fichier sans soucis. Mais je ne comprends pas pourquoi munmap() n'adapte pas la taille du fichier malgres le fait que l'argument len soit plus grand que la taille reel du fichier.

    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
     
    int     main(int ac, char **av)
    {
      int   fd;
      int   fsize;
      void  *file;
     
      if (-1 == (fd = open("all_users", O_CREAT | O_RDWR, 0755)))
        {
          printf("open failed\n");
          return (EXIT_FAILURE);
        }
      fsize = lseek(fd, 0, SEEK_END);
      file = mmap(NULL, fsize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, 0);
      if (file == MAP_FAILED)
        {
          printf("mmap failed %d\n", fsize);
          return (EXIT_FAILURE);
        }
      if (ac == 3)
        fsize = add_user(av[1], av[2], file, fsize);
    /*add user ecrit le header de 8octects et 10 structures de 200octects a la suite du pointeur file on optient donc une fsize de 2008*/
      printf("fsize = %d\n", fsize);
      if (-1 == munmap(file, fsize))
        printf("mmap failed\n");
      return (EXIT_SUCCESS);
    }
    Donc pour le moment la taille du fichier depend directement de la taille que je lui ai donne au debut(961 dans mon cas) et ne depend absolument pas de ce que j'ecris dedans grace a mmap.

    Je suppose donc qu'il me manque quelquechose pour que mmap adapte lui meme la taille de mon fichier. Je pensais que c'etait le param len de munmap() mais visiblement pas.

    En gros comment faire pour changer la taille d'un fichier mappe par mmap ?

    Merci d'avance pour votre aide !

  2. #2
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    C'est pourtant écrit clairement dans la norme :
    http://www.opengroup.org/onlinepubs/...ions/mmap.html
    If the size of the mapped file changes after the call to mmap() as a result of some other operation on the mapped file, the effect of references to portions of the mapped region that correspond to added or removed portions of the file is unspecified.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 56
    Points : 44
    Points
    44
    Par défaut
    Merci beaucoup je suis probablement passe a cote quand j'ai lu la doc ...

    Mais y'aurait pas moyen de faire une "esquive" consistant a changer la taille du fichier a la main ?

    Merci d'avance

  4. #4
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    Pas à ma connaissance, certains systèmes offrent MAP_AUTOGROW mais ça n'est ni portable, ni courant, ni sur linux.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 56
    Points : 44
    Points
    44
    Par défaut
    Oui j'avais vu AUTOGROW mais effectivement dans mon ca ne fait pas l'affaire etant donne que je dois faire du multi plateforme (Linux/Unix/Solaris).

    Je vais essayer en faisant des writes dans le fichier histoire d'adater sa taille a la hausse. Pour la taille a la baisse pour le moment je pense que je ne vais pas faire ...

    Je vais faire des test je te tiendrais au courrant

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 56
    Points : 44
    Points
    44
    Par défaut
    Bon alors j'ai fais deux trois tests hiere soir et j'ai reussis a faire ce que je voulais.

    Par exemple si j'ai un fichier de contenant 1 octect je veux y copier une structure qui en fait 8.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      fize = taille_du_fichier_a_l_ouverture
      objectif = sizeof(t_users_index); /*Calcule de la taille necessaire dans le fichier pour copier la struct*/
      fsize = update_fsize(objectif, fsize, fd); /*ecrit n octects dans le fichier pour avoir un fsize == objectif*/
      memcpy(file, (void*)&idx, sizeof(t_users_index)); /*Copie de la structure*/
      file = (void*)((int)file + sizeof(t_users_index));/*On avance le pointeur file*/
    Bon c'est relativement moche mais ca fonctionne bien et le fichier devient plus gros en fonction des besoins

    Merci pour ton aide.

  7. #7
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    Citation Envoyé par Niklaos Voir le message
    Bon alors j'ai fais deux trois tests hiere soir et j'ai reussis a faire ce que je voulais.

    Par exemple si j'ai un fichier de contenant 1 octect je veux y copier une structure qui en fait 8.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      fize = taille_du_fichier_a_l_ouverture
      objectif = sizeof(t_users_index); /*Calcule de la taille necessaire dans le fichier pour copier la struct*/
      fsize = update_fsize(objectif, fsize, fd); /*ecrit n octects dans le fichier pour avoir un fsize == objectif*/
      memcpy(file, (void*)&idx, sizeof(t_users_index)); /*Copie de la structure*/
      file = (void*)((int)file + sizeof(t_users_index));/*On avance le pointeur file*/
    Bon c'est relativement moche mais ca fonctionne bien et le fichier devient plus gros en fonction des besoins

    Merci pour ton aide.
    On peut avoir le code complet car j'ai un doute sur ce que tu fais.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 56
    Points : 44
    Points
    44
    Par défaut
    Ok

    Bon fais pas attention au write de 1 extremement moche je dois rendre ca ce soir et j'ai pas le temps de mieux faire :p
    J'y retoucherais a tete reposee apres avoir dormis

    Merci

    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
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
     
    static int      update_fsize(int objectif, int fsize, int fd)
    {
      --fsize;
      while (++fsize <= objectif)
        {
          write(fd, " ", 1);
        }
      return (fsize);
    }
     
    static int      init_file(char **av, void *file, int fsize, int fd)
    {
      t_users_index idx;
      t_user        user;
      int           objectif;
     
      strcpy(idx.magic, MAGIC);
      idx.nbr_users = 1;
      idx.st_user_size = sizeof(t_user);
      strcpy(user.login, av[1]);
      strcpy(user.password, av[2]);
      strcpy(user.root, USER_DIR);
      strcat(user.root, av[1]);
      objectif = sizeof(t_users_index);
      fsize = update_fsize(objectif, fsize, fd);
      memcpy(file, (void*)&idx, sizeof(t_users_index));
      file = (void*)((int)file + sizeof(t_users_index));
      objectif += sizeof(t_user);
      fsize = update_fsize(objectif, fsize, fd);
      memcpy(file, (void*)&user, sizeof(t_user));
      file = (void*)((int)file + sizeof(t_user));
      return (sizeof(t_user) + sizeof(t_users_index));
    }
     
    static int      insert_file(char **av, void *file, int fsize, int fd)
    {
      t_users_index *idx;
      t_user        *user;
     
      idx = (t_users_index*)file;
      if (strcmp(idx->magic, MAGIC) != 0)
        {
          printf("Corrupted Memory\n");
          exit(EXIT_FAILURE);
        }
      fsize = update_fsize(((idx->nbr_users + 1) * sizeof(t_user)), fsize, fd);
      user = (t_user*)((int)file + sizeof(t_users_index) +
                       (idx->nbr_users * sizeof(t_user)));
      idx->nbr_users++;
      strcpy(user->login, av[1]);
      strcpy(user->password, av[2]);
      strcpy(user->root, USER_DIR);
      strcat(user->root, av[1]);
      return (fsize);
    }
     
    int             add_user(char **av, void *file, int fsize, int fd)
    {
      printf("NEW user\nLogin : %s\nPassword : %s\n", av[1], av[2]);
      if (fsize < 8)
        {
          fsize = init_file(av, file, fsize, fd);
          return (fsize);
        }
      fsize = insert_file(av, file, fsize, fd);
      return (fsize);
    }
     
    static void     dump_memory(void* file)
    {
      t_users_index *idx;
      t_user        *user;
      int           i;
     
      idx = (t_users_index*)file;
      if (strcmp(idx->magic, MAGIC) != 0)
        {
          printf("Corrupted Memory\n");
          exit(EXIT_FAILURE);
        }
      i = -1;
      printf("idx : %d\n", idx->nbr_users);
      user = (t_user*)((int)file + sizeof(t_users_index));
      while (++i != idx->nbr_users)
        {
          printf("Login : %s\nPassword : %s\nRoot : %s\n"
                 , user->login, user->password, user->root);
          user = (t_user*)((int)user + idx->st_user_size);
        }
    }
     
    int             main(int ac, char **av)
    {
      int           fd;
      int           fsize;
      void          *file;
     
      if (-1 == (fd = open(FNAME, O_CREAT | O_RDWR, 0755)))
        {
          printf("open failed\n");
          return (EXIT_FAILURE);
        }
      fsize = lseek(fd, 0, SEEK_END);
      file = mmap(NULL, fsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
      if (file == MAP_FAILED)
        {
          printf("mmap failed %d\n", fsize);
          return (EXIT_FAILURE);
        }
      if (ac == 3)
        fsize = add_user(av, file, fsize, fd) + 1;
      else
        dump_memory(file);
      if (-1 == munmap(file, fsize))
        printf("mmap failed\n");
      return (EXIT_SUCCESS);
    }

  9. #9
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    C'est bien ce que je pensais, arrête le carnage, tu tapes dans de la mémoire que tu n'as pas allouer, j'ai valgrind qui hurle à la mort. Heureusement, j'ai trouvé une solution au problème, non portable certe, mais au moins définie sur linux : http://www.gnu.org/software/libc/man...html#File-Size.
    Cordialement.

Discussions similaires

  1. Réponses: 2
    Dernier message: 12/05/2010, 14h16
  2. utiliser un tableau pour stocker des valeurs alphanum
    Par tibofo dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 26/03/2010, 10h07
  3. [Python] Est-ce une bonne idée d'utiliser des modules pour stocker des objets ?
    Par Neolander dans le forum Développement 2D, 3D et Jeux
    Réponses: 1
    Dernier message: 05/04/2008, 15h45
  4. Files Mapping pour stocker des structures de données
    Par Targan dans le forum Débuter
    Réponses: 0
    Dernier message: 27/12/2007, 12h38
  5. [C++] quelle structure de donnée utiliser pour stocker des vertices ?
    Par johnnyjohnny dans le forum Développement 2D, 3D et Jeux
    Réponses: 14
    Dernier message: 14/07/2007, 22h44

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